在研究这个完全相同的问题时,我遇到了一个我认为合理的解决方案。不幸的是,该解决方案不会按照要求自动混淆原生 Java 代码和 JNI 方法,但我仍然认为值得分享。
引用来源:
我在这里介绍一个简单的技巧,它允许混淆 JNI 层,在 Java 和本机端将方法名称重命名为无意义的名称,同时保持源代码相对可读和可维护且不影响性能。
让我们考虑一个例子,初始情况:
class Native {
native static int rotateRGBA(int rgb, int w, int h);
}
extern "C" int Java_pakage_Native_rotateRGBA(JNIEnv *env, jclass, int rgb, int w, int h);
在上面的示例中,Proguard 无法混淆方法名称 rotateRGBA,它在 Java 端和本机端仍然可见。
解决方案是直接在源代码中使用无意义的方法名称,同时注意尽量减少代码的可读性和可维护性。
class Native {
private native static int a(int rgb, int w, int h); //rotateRGBA
static int rotateRGBA(int rgb, int w, int h) {
return a(rgb, w, h);
}
}
// rotateRGBA
extern "C" int Java_pakage_Native_a(JNIEnv *env, jclass, int rgb, int w, int h);
JNI方法被重命名为无意义的a。但是 Java 端的调用被有意义地命名的方法 rotateRGBA 包装。Java 客户端继续像以前一样调用 Native.rotateRGBA(),而完全不受重命名的影响。
有趣的是,新的 Native.rotateRGBA 方法不再是原生的,因此可以被 Proguard 随意重命名。结果是在 Dalvik 和本机端,名称 rotateRGBA 完全从混淆代码中消失。更重要的是,Proguard 优化了包装方法,从而消除了包装本机调用的(可忽略的)性能影响。
结论:从混淆代码(Dalvik 字节码和本机库)中消除了 JNI 方法名称,对可读性的影响最小,对性能没有影响。
来源:混淆 JNI 表层
我仍在寻找一种可以自动混淆原生 Java 代码和相关 JNI 的工具。