Is it possible to tell the ProGuard to completely skip the class if there is native function in it ?
-keepclasseswithmembernames class * { native <methods>; }
Above doesn't work for me because it keeps the class names and the native functions names but obfuscates other members
I'd like to know if it's possible to keep everything in such classes without explicitly specifying every class
Thank you
Use these rules:
Note, that "completely skipping" class with Proguard is a always bad idea, because it may also indirectly keep some classes, used from code of your kept classes. Instead I recommend the following mode:
It will allow shrinking and optimizing code of non-native methods, present in the same class.
You can do even better: if your native methods are resolved by names (e.g. they are called something like
Java_com_your_packages_methodName
), and you don't useRegisterNatives
to register them explicitly, you may allow shrinking away unused native methods by removing the second rule, which will leave onlyIf you want some of class members to be accessible from JNI (e.g. you have some static callback methods to be called from native code), you should keep them explicitly: annotate each such member with specialized annotation and use an annotation-based rule to keep them:
You can use your own annotation in place of the one from Android support library — in fact, it is better to use your own in order to avoid interference from existing consumer rules, coming from Android Gradle plugin or other libraries.
In general, I recommend you to reduce the amount of friction between JNI and Java code as much as possible. If you have multiple related Java methods, called from JNI, try to put them together in the same method:
Throw your exceptions from Java code (you was going to reflectively invoke their constructors anyway, so may as well invoke a static helper method instead):
If you have a class, that has to be passed to JNI, try to pass individual fields instead of that class:
If you have a native peer class (a class, closely connected to some structure in native memory), you can keep a pointer to native structure in that class in
long
field, and pass that field to native methods. Then in native methods cast thatlong
to pointer:And in native code:
These simple rules will allow you to fully obfuscate any huge application using JNI, except for a single small class, that contains all
native
methods.I suggest you go even further and push for repackaging classes, referenced by native callbacks.
Instead of
You can omit a type of parameter by replacing it with
Object
:This will let you obfuscate and repackage even types of callback arguments.
Use -keep instead of -keepclasseswithmembernames
For more info: https://jebware.com/blog/?p=418