Mic*_*Tin 0 android proguard android-proguard
如果类中有本机函数,是否可以告诉 ProGuard 完全跳过该类?
-keepclasseswithmembernames class * { native <methods>; }
Run Code Online (Sandbox Code Playgroud)
上面对我不起作用,因为它保留了类名称和本机函数名称,但混淆了其他成员
我想知道是否可以将所有内容保留在此类中,而无需显式指定每个类
谢谢
\n\n\n如果类中有本机函数,是否可以告诉 ProGuard 完全跳过该类
\n
使用这些规则:
\n\n\n-keepclasseswithmembers class com.your.packages.** {\n 本机 <方法>;\n}\n-keepclassmembers class com.your.packages.** {\n 本机 <方法>;\n}\n\n\n
请注意,使用 Proguard“完全跳过”类总是一个坏主意,因为它也可能间接保留一些类,这些类是从您保留的类的代码中使用的。相反,我推荐以下模式:
\n\n\n-keepclasseswithmembers,允许收缩,允许优化class com.your.packages.** {\n native <methods>;\n}\n-keepclassmembers class com.your.packages.** {\n native <methods>;\ n}\n\n\n
它将允许缩小和优化同一类中存在的非本机方法的代码。
\n\n您可以做得更好:如果您的本机方法是通过名称解析的(例如,它们被称为类似的东西Java_com_your_packages_methodName
),并且您不使用RegisterNatives
显式注册它们,则可以通过删除第二条规则来允许缩小未使用的本机方法,该规则只会离开
\n-keepclasseswithmembers、允许收缩、允许优化类 com.your.packages.** {\n 本机 <methods>;\n}\n\n\n
如果您希望某些类成员可以从 JNI 访问(例如,您有一些要从本机代码调用的静态回调方法),则应该显式保留它们:使用专门的注释来注释每个此类成员,并使用基于注释的规则来保留它们他们:
\n\n\n-keepclassmembers,允许优化,includedescriptorclasses class com.your.packages.** {\n @android.support.annotation.Keep *;\n}\n\n\n
您可以使用自己的注释来代替 Android 支持库 \xe2\x80\x94 中的注释,事实上,最好使用自己的注释,以避免来自 Android Gradle 插件或其他库的现有消费者规则的干扰。
\n\n一般来说,我建议您尽可能减少 JNI 和 Java 代码之间的摩擦。如果您有多个从 JNI 调用的相关 Java 方法,请尝试将它们放在同一个方法中:
\n\n@Keep\npublic static void callback(int action, String arg) {\n switch (action) {\n ...\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n从 Java 代码中抛出异常(无论如何,您都会反射性地调用它们的构造函数,因此也可以调用静态帮助器方法):
\n\n@Keep\npublic static void throwException(int type, String message) {\n switch (type) {\n case 0:\n throw new BadThingsHappenedException(message);\n case 1:\n throw new AllHopeIsLostError();\n ...\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n如果您有一个类,必须将其传递给 JNI,请尝试传递单个字段而不是该类:
\n\npublic final class DataClass {\n int intField;\n String stringField;\n\n public void doSomeNativeOperation() {\n JNI.doSomeNativeOperation(this);\n }\n}\n\npublic final class JNI {\n public static void doSomeNativeOperation(DataClass arg) {\n doSomeNativeOperation0(arg.intField, arg.stringField);\n }\n\n private static native void doSomeNativeOperation0(int intField, String stringField);\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n如果您有一个本机对等类(与本机内存中的某些结构紧密连接的类),您可以在long
字段中保留指向该类中本机结构的指针,并将该字段传递给本机方法。然后在本机方法中将其转换long
为指针:
public final class Peer {\n long pointer;\n\n // constructor is invoked from JNI\n @Keep\n protected Peer(long pointer) {\n this.pointer = pointer;\n }\n\n public void doSomeNativeOperation() {\n JNI.doSomeNativeOperation(this);\n }\n}\n\npublic final class JNI {\n public static void doSomeNativeOperation(Peer peer) {\n doSomeNativeOperation0(peer.pointer);\n }\n\n private static native void doSomeNativeOperation0(long pointer);\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n在本机代码中:
\n\nvoid JNIEXPORT Java_com_your_packages_methodName(JNIEnv* env, jobject type, jlong ptr) {\n struct my_struct peer = (struct my_struc*) (intptr_t) ptr;\n ...\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n这些简单的规则将允许您使用 JNI 完全混淆任何大型应用程序,但包含所有方法的单个小类除外native
。
我建议您更进一步,推动重新打包由本机回调引用的类。
\n\n代替
\n\n@Keep\npublic static void callback(YourCustomType arg) {\n ...\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n您可以通过将其替换为来省略某种类型的参数Object
:
@Keep\npublic static void callback(Object arg) {\n // this cast won\'t make much difference in performance, but it makes huge\n // difference for Proguard!\n YourCustomType instance = (YourCustomType) arg;\n\n ...\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n这将允许您混淆和重新打包甚至类型的回调参数。
\n 归档时间: |
|
查看次数: |
3388 次 |
最近记录: |