使用 progaurd 混淆 JNA 结构时 getFieldOrder() 中的异常

Exception in getFieldOrder() when obfuscating JNA Structure using progaurd

我的未混淆代码有效..

当 运行 通过 Proguard 混淆时 -- 只需 1 遍优化 我收到以下错误:

Exception in thread "main" java.lang.Error: Structure.getFieldOrder() on class com.sun.jna.platform.mac.SystemB$Timeval does not provide enough names [0] ([]) to match declared fields [2] ([tv_sec, tv_usec])
    at com.sun.jna.Structure.getFields(Unknown Source)
    at com.sun.jna.Structure.deriveLayout(Unknown Source)
    at com.sun.jna.Structure.calculateSize(Unknown Source)
    at com.sun.jna.Structure.allocateMemory(Unknown Source)
    at com.sun.jna.Structure.ensureAllocated(Unknown Source)
    at com.sun.jna.Structure.ensureAllocated(Unknown Source)
    at com.sun.jna.Structure.getPointer(Unknown Source)
    at oshi.util.platform.mac.SysctlUtil.sysctl(Unknown Source)
    at oshi.software.os.mac.MacOperatingSystem.<clinit>(Unknown Source)
    at oshi.SystemInfo.createOperatingSystem(Unknown Source)
    at oshi.util.Memoizer.get(Unknown Source)
    at oshi.SystemInfo.getOperatingSystem(Unknown Source)

我尝试了几个 on keep 指令如下:

-keep class com.sun.** { *; }

-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

-keep class com.sun.jna.**{ *; }
-keep class * implements  com.sun.jna.**{ *; }

-keep class oshi.**{ *; }
-keep class * implements  oshi.**{ *; }

-keepclassmembers class * extends com.sun.jna.** {
    <fields>;
   <methods>;
}

-keepclassmembers class * extends oshi.** {
    <fields>;
   <methods>;
}

如何配置 Proguard 以避免此异常?

从 JNA 5.x 开始,Structure class 字段用 @FieldOrder 注释标识。对于导致问题的 Timeval 结构,它的定义如下:

@Structure.FieldOrder({ "tv_sec", "tv_usec" })
class Timeval extends Structure {
    public NativeLong tv_sec; // seconds
    public int tv_usec; // microseconds
}

堆栈跟踪表明它找到了 public 字段(正确)但没有找到注释声明的字段顺序。

表示Proguard会混淆注解,这很可能是问题的根源。

JNA's FAQ 建议使用以下语法。可能需要更广泛的通配符定义,而不是明确定义 <fields><methods>.

-dontwarn java.awt.*
-keep class com.sun.jna.* { *; }
-keepclassmembers class * extends com.sun.jna.* { public *; }

由于注释在 JNA 的结构 class 中定义为 @interfacethis question 的答案所建议的解决方案表明以下内容应该可以解决问题:

# Annotated interfaces (including methods which are also kept in implementing classes)
-keep @com.sun.jna.Structure.FieldOrder interface * {
    *;
}

其他可能有效的解决方案,范围更广:

  • -keepattributes Annotation
  • -keepattributes *Annotation*