Proguard - Error: A JNI error has occured - java

I've been trying to use ProGuard to obfuscate an application of mine. I have disabled every option exception for obfuscate. Loader is my main class.
The screenshot below is the result when I try to run my obfuscated jar.
No errors were given while obfuscating either.
My config
-injars 'C:\Users\Corsair\Desktop\obfuscate\Example.jar'
-outjars 'C:\Users\Corsair\Desktop\obfuscate\ExampleOut.jar'
-libraryjars 'C:\Program Files\Java\jre1.8.0_91\lib\rt.jar'
-dontskipnonpubliclibraryclassmembers
-dontshrink
-dontoptimize
-dontusemixedcaseclassnames
-dontpreverify
-dontnote
-dontwarn
-verbose
-keep class Loader

If this is the only configuration that you are using, also native methods will get obfuscated. As a result, their name will not match the ones in the native library anymore, and thus you will see an error like this when trying to load the library using System.loadLibrary.
You need to add at least a rule like this:
-keepclasseswithmembernames,includedescriptorclasses class * {
native <methods>;
}
This will instruct ProGuard to keep all native methods in any class it processes.
Edit:
Additional rules that are needed to get it working:
Remove -dontpreverify, preverify is needed for Java 7+
Keep the main method
This will keep the main method:
-keep class Loader {
public static void main(...);
}

You have to exclude certain classes from obfuscating like bean classes, callback classes and native classes. In the official examples the following is mentioned:
Processing native methods
If your application, applet, servlet, library, etc., contains native methods, you'll want to preserve their names and their classes' names, so they can still be linked to the native library.
-keepclasseswithmembernames,includedescriptorclasses class * {
native <methods>;
}
Note: We don't want to preserve all classes or all native methods; we just want to keep the relevant names from being obfuscated.
Processing callback methods
If your application, applet, servlet, library, etc., contains callback methods, which are called from external code (native code, scripts,...), you'll want to preserve them, and probably their classes too. They are just entry points to your code, much like, say, the main method of an application.
-keep class mypackage.MyCallbackClass {
void myCallbackMethod(java.lang.String);
}
Processing bean classes
If your application, applet, servlet, library, etc., makes extensive use of introspection on bean classes to find bean editor classes, or getter and setter methods, then configuration may become painful. There's not much else you can do than making sure the bean class names, or the getter and setter names don't change
Helpful: to use wildcards in class names and method signatures
-keep class mybeans.** {
void set*(***);
void set*(int, ***);
boolean is*();
boolean is*(int);
*** get*();
*** get*(int);
}
Also some other scenarios (Ressources, Serialization classes) can lead to problems. Please refer to the whole guide for these
ProGuard Official: Examples

Related

How to keep java.lang.reflect when use proGuard

In my application I want use this library : https://github.com/xmuSistone/AndroidPileLayout
And I want use proguard in my project, when proguard my project show me may bugs.
For fix proguard, the library developer say:
proguard works wrong when you are using java.lang.reflect api, please
check your own code.
How can I fix it and keep java.lang.reflect?
Please help me
Reflection will need to have absolute path the the classes and its respective methods. So, you need to tell proguard to leave the stuff you need alone. You can describe this in your proguard-rules.pro file.
Example:
-keep public class fully_qualified_classname
-keepclassmembers public class fully_qualified_classname {
# will ignore all methods
public <methods>;
public static final String static_instance_variable_if_any;
}

Proguard: How to prevent the renaming of Packagename in Android?

I use a c++ native Library in my Android project, but when Proguard is Enabled, the app crashes. My code in c++ depends on the packagename, so I need to prevent the packagename from being renamed by Proguard.
I used this rule so far, but it's not working:
-keepclasseswithmembernames class * {
native <methods>;
}
I appreciate you support.
Try this configuration to prevent specified package names from being obfuscated.
-keeppackagenamesĀ [package_filter]
A filter is a list of comma-separated names that can contain wildcards.

Android Studio: How to compile with customized class but still use module dependency

Say an Android app uses a jar library and everything is working fine when the library is specified as a dependency:
dependencies {
...
...
compile 'org.example:example:1.1.1'
...
}
BUT : one of the classes in the org.example code needs to be tweaked.
One approach is to obtain the source code and put all of that in the java folder, and remove the module. When the tweak is made, that, and the entire library will be compiled.
Another approach is to make the tweak, compile, and replace the .class file within the .jar file.
Both of those methods have their drawbacks.
My question is: Is there an easier way to tweak code in a library?
When I tried just creating the package, placing the class that needed changing into the java folder, I got an error:
Error converting bytecode to dex:
Cause: com.android.dex.DexException: Multiple dex files define Lorg/example/ClassNeedingChange;
I just wondered if there was a trick to getting code in the Java folder to override whats in a library jar file.
Additional Info:
Although not stated specifically above, the class that needs tweaking is buried in the library and is referenced by the library's code; I don't call it directly. For the simple case where the class that needed tweaking is one that my code (and only my code) called directly, then it would be a simple matter of extending the class using the Java construct. But for this simple case, I would not need to post this question.
Extend the class that needs tweaked in your code, and override the appropriate method.
Class A extends TweakMe {
#Override
public void someTweakedMethod() {
//Do stuff
}
}

Proguard warnings despite kept classes

I'm using Proguard to shrink my code. My strategy is to enable it and then follow the warnings to keep anything it complains about. If there are outside libraries, I try to follow the Proguard instructions the authors make available. Many instructions include a -dontwarn flag. If I disable the -dontwarn flag, I will get warnings. If we are keeping most classes via -keep flag, why do warnings still come up?
Example:
-keep class javax.** { *; }
# for butterknife
-keep class butterknife.** { *; }
-dontwarn butterknife.internal.**
-keep class **$$ViewBinder { *; }
-keepclasseswithmembernames class * {
#butterknife.* <fields>;
}
-keepclasseswithmembernames class * {
#butterknife.* <methods>;
}
Warning:butterknife.internal.ButterKnifeProcessor: can't find referenced class javax.annotation.processing.AbstractProcessor
Warning:butterknife.internal.ButterKnifeProcessor: can't find referenced class javax.annotation.processing.ProcessingEnvironment
Warning:butterknife.internal.ButterKnifeProcessor: can't find referenced class javax.lang.model.element.TypeElement
Warning:butterknife.internal.ButterKnifeProcessor: can't find referenced class javax.lang.model.element.Element
Warning:butterknife.internal.ButterKnifeProcessor: can't find referenced class javax.annotation.processing.Filer
Warning:butterknife.internal.ButterKnifeProcessor: can't find referenced class javax.tools.JavaFileObject
...
There are many warnings in ProGuard meaning different things. This particular one:
Warning:A: can't find referenced class B
Means that while ProGuard was processing class A it encountered reference to class B. But class B wasn't included as a source (-injars class_path) or as a library (-libraryjars class_path).
First note that for this particular warning in case of standard Android build chain adding -keep rules will not help. ProGuard transitively keeps referenced code.
This warning can happen for several reasons. Often a library X can contain code that uses another library Y. And X uses Y optionally - only when Y is present on the classpath, X doesn't enforce presence of Y. This way ProGuard is unable to find classes from Y.
To get rid of the warnings you have to either add Y as a dependency or ignore the relevant warnings.
In case of ButterKnife the situation is slightly different. Butterknife uses annotation processing. And it contains both the library and annotation processor in one dependency (latest version 7.0.1). So class butterknife.internal.ButterKnifeProcessor is still present in the compiled classes (even though it's work is already finished - used during java compilation). And ProGuard tries to process it. ProGuard fails to find the missing classes because they were used only during annotation processing and are not present for ProGuard processing.
In this case it's really necessary to ignore the warnings.

Find unused classes in a Java Eclipse project

I have a large Eclipse project in which there exist several classes which, although they ceased to be used anywhere, were never marked #Deprecated.
How can I easily find all of these?
I also like to use UCDetector:
UCDetector (Unecessary Code Detector) is a Open Source eclipse PlugIn Tool to find unecessary (dead) public java code. It also tries to make code final, protected or private.
Bonus: it can also find cyclic dependencies between classes
(also a number of other tools -- including Findbugs -- knows how do do that too)
Caveat: Cid mentions in the comments:
UCDetector shall not work if there are interface implementations which will be known only at runtime.
It incorrectly marks the implementation classes as unused.
Update 2017: static code analysis has evolved quite a bit in 8 years.
Using SonarLint for Eclipse, you can use the the latest SonarJava 4.6 plugin to analyze your code.
It will find dead code.
ProGuard can be used to print a report of unused classes/methods. It's a pain to supply all the dependent jars to it, though.
These options list unused classes, fields, and methods in the application mypackage.MyApplication:
-injars in.jar
-libraryjars <java.home>/lib/rt.jar
-dontoptimize
-dontobfuscate
-dontpreverify
-printusage
-keep public class mypackage.MyApplication {
public static void main(java.lang.String[]);
}
Just use Analyze | Inspect Code with appropriate inspection enabled (Unused declaration under Declaration redundancy group).
Using IntelliJ 11 CE you can now "Analyze | Run Inspection by Name ... | Unused declaration"

Categories

Resources