Proguard issues with jar files, how to find the missing jar? - java

When I try to export my apk with Proguard I get a lot of errors (over 400) similar to:
Warning: org.codehaus.jackson.jaxrs.JsonMappingExceptionMapper: can't find superclass or interface javax.ws.rs.ext.ExceptionMapper
and
org.codehaus.jackson.xc.DataHandlerJsonDeserializer$1: can't find superclass or interface javax.activation.DataSource
I am using the Jackson Json library, and the errors seem related to that.
Researching this error I found the following from Proguards FAQ:
If there are unresolved references to classes or interfaces, you most likely forgot to specify an essential library. For proper processing, all libraries that are referenced by your code must be specified, including the Java run-time library. For specifying libraries, use the -libraryjars option.
Searching around on SO I found a lot of unanswered questions related to this, but the general sense was that the jar file I am using (in this case Jackon JSON) is relying on more libraries and they need to be added to Proguard's config file some how.
However, I can't figure out how to determine what jars are needed and where they are. The warnings mention a lot of different packages such as javax.ws.rs.ext, org.joda.time, org.codehaus.stax2, javax.xml.stream, etc.
How do I determine what jars contain those packages? For example, what jar is required for the javax.ws.rs.ext.** classes?
How do I figure out where those jars are and what path would be used with -libraryjars in Proguard?
Thanks much
Edit: I should also mention that I am using an Android Library Project setup. The jars are in the main Library project, and the actual working project has their build paths including the jars in the Library project. Don't know if that makes a difference but thought I should mention it.
Update Just to test, I completely removed the jackson far from the build path and from my code and now Proguard completes successfully. The questions still remain... What is the correct approach for handling these errors?
Does the Android export wizard in Eclipse automatically add the /lib/ jars to proguard or do they all have to be added manually in the proguard config file like this:
-libraryjars C:/Project/lib/somjar.jar
I did try that for the jackson one but it didn't make any difference. Does this mean I also have to find all of the jars that are needed for the classes mentioned in the warnings and add those? Would they be in the sdk or in the java installation?
Sorry if these are stupid questions, but I have been trying to figure this out for the last couple hours and have no idea what to do.
Thanks again
Update Again
So more searching, combined with Benjamin's suggestion, I found some of the missing classes were in rt.jar, which is in the jdk's lib folder. So I ended up adding
-libraryjars <java.home>/lib/rt.jar
To the proguard.cfg file and brought the warnings from 485 down to 204. Hey I guess that's something... The remaining warnings describe classes that I cannot find at all. The app works just fine without running proguard, so these classes must be somewhere right? Or are these warnings that I should use -dontwarn with?
The remaining classes are in these packages:
org.joda.time.
org.codehaus.stax2.
javax.ws.rs.
So now I just need a way to figure out:
What jars have these classes
Where are these jars so I can include them in the proguard config file

I've had similar problems with Proguard and similar errors I was using an osmdroid.jar which built OK unobfuscated. This jar must have had external dependencies which my application didn't need. Fortunately the authors listed the jars needed and once I downloaded them and told Proguard via the -libraryjars option, the Proguard build was OK.
Re your missing jars (which you probably don't really need, but Proguard thinks you might!), you should find them at:
org.joda.time
(The jar's inside the zip)
org.codehaus.stax2.
javax.ws.rs.

I only can provide an answer for the first part:
Give
http://www.findjar.com
a try, there you might find the names of the needed jar files
like so

You don't need to include the libraries for Proguard; you need to instead instruct Proguard to keep the class names and some other stuff. I toyed around with it a bit myself, and I ended up with something similar to this discussion:
-keepnames class org.codehaus.** { *; }
-keepattributes *Annotation*,EnclosingMethod
-dontwarn org.codehaus.jackson.**
If you're still experiencing crashes—and I would suggest testing vigorously!—you might want to keep Jackson completely intact with:
-keep class org.codehaus.** { *; }
-keepattributes *Annotation*,EnclosingMethod
-dontwarn org.codehaus.jackson.**
(Note that the latter produces a larger file.)

Related

Proguard obfuscation of multi jar project

I have successfully configured Proguard with Maven to obfuscate a jar, and its dependant jar. I have managed to get both obfuscations to use the same mapping file, so that one jar can call the methods of the other. The problem I am facing, is that Proguard is not keeping unique names across the obfuscated jars; both obfuscated jars contain a class called
f.b.class
As there are two classes called f.b.class (one in each jar), priority is being given to the class inside the calling jar, which is causing problems.
Has anybody experienced this before and are you aware of a solution for this. Currently I am using the
-keeppackagenames
switch to ensure that the package hierarchy remain different so that any duplicated class names do not conflict. Ideally I would like to remove all package names
The switch
-useuniqueclassmembernames
has also been applied but it clearly only applies this to the jar currently being obfuscated. It does don't look and previously obfuscated jars to ensure uniqueness across jars.
Thanks
To resolve this I ended up using the -keeppackagenames option. It is not a solution, but a work around.

Android, Proguard & XmlPullParser: NoSuchMethodError

I am using XmlPullParser and when the app pass throught the Proguard, and the apk is running on device, it give me the following error:
08-06 17:10:26.717: E/AndroidRuntime(2527):
Caused by: java.lang.NoSuchMethodError: org.xmlpull.v1.XmlPullParser.d
I have added -ignorewarnings in my proguard.cfg or otherwise there is no way to pass the Proguard.
Here is a link to my proguard.cfg file.
You obfuscated away a method you shouldn't have. You need to keep the pull parser code intact. Add:
-keep public class org.xmlpull.**
to your proguard.cfg file.
what you want in your proguard config file is -keep instead of -ignorewarnings
-keep class org.xmlpull.** { *; }
See the following url for some more details
http://android-developers.blogspot.com/2010/09/proguard-android-and-licensing-server.html
But Wait, My App is Crashing Now
Most crashes happen because Proguard has obfuscated away something that your application needs,
such as a class that is referenced in the AndroidManifest or within a
layout, or perhaps something called from JNI or reflection. The
Proguard configuration provided here tries to avoid obfuscating most
of these cases, but it’s still possible that in edge cases you’ll end
up seeing something like a ClassNotFoundException.
You can make edits to the procfg.txt file to keep classes that have
been obfuscated away. Adding:
-keep public class * [my classname]
should help. For more information about how to prevent Proguard from
obfuscating specific things, see the Proguard manual. Specifically,
the keep section. In the interest of security, try to keep as little
of your application unobfuscated as possible.
The standard settings provided in procfg.txt will be good for many
applications, and will catch many common cases, but they are by no
means comprehensive. One of the things that we’ve done is had Proguard
create a bunch of output files in the obf directory to help you debug
these problems.
The mapping.txt file explains how your classes have been obfuscated.
You’ll want to make sure to keep this around once you have submitted
your build to Market, as you’ll need this to decipher your stack
traces.

How to exclude .java files from validation in Eclipse

In my source tree have Java code which is automatically generated from XSD files. This code is full of warnings which is messing other legitimate warnings. How do I exclude such folders or packages from validation?
Have read several similar questions, but those suggest to exclude folders from appropriate validator types found in Preferences. However I can't find validator for .java files.
Any help would be appreciated. Thanks!
Sasa
You need the feature 'ignore optional compiler problems' from the very latest eclipse milestone:
http://download.eclipse.org/eclipse/downloads/drops4/S-4.2M6-201203151300/eclipse-news-M6.html
Might be a workaround possible without that, like putting the auto generated files in a different project. But what you want to do is exactly the intended use of that feature.

Minimizing jar dependency sizes

an application I have written uses several third party jars. Sometimes only a small portion of the entire 50kB to 1.7mB jar is used - one or two function calls or classes.
What is the best way to reduce the jar sizes. Should I download the sources and build a jar with just the classes I need? What existing tools can help automate this (ex I briefly looked at http://code.google.com/p/jarjar/)?
Thank you
Edit 1:
I would like to lower the size of my third party 'official' jars like swingx-1.6.jar (1.4 MB), set-3.6 (1.7 MB) glazedlists-1.8.jar (820kB) , etc. so that they only contain the bare minimum classes I need
Edit 2:
Minimizing a jar by hand or by using a program like proguard is further complicated if the library uses reflection.
Injection with google guice does not work anymore after obfuscation with proguard
The answer by cletus on another post is very good How to determine which classes are used by a Java program?
Proguard would be an option. It can eliminate unused classes and methods. You can also use it to obfuscate, which can further reduce the size of your final jar. Be aware that class loading by name is liable to break unless care is taken to keep the affected classes unobfuscated.
I've found Proguard quite effective - can be a bit cryptic to understand at the outset. But I don't have any experience with similar to offer a comparison.
First of all, if you use only one class from JAR file this does not mean that this class does not use other classed from that JAR.
The option for you, if you use open source JARs, is to get sources of that JAR, attach them to your project, remove unnecessary stuff and build the changes by yourself.
You could add GenJar as an Ant task and use it to build the JAR. As it says on the library's home page,
GenJar is a specialized Ant task that
builds jar files based on class
dependencies rather than simply the
contents of a directory.
You can find it on SourceForge.

Netbeans Obfuscation

I'm very new to obfuscation and don't have a lot of experience with ant. Come someone provide me a way to obfuscate a regular Java application with ProGuard (or any other open source obfuscator). Currently I'm using NetBeans 6.5.1, and only see the obfuscation ability if I create a JAVA ME, and not a Java Application like I have. I've looked at http://wiki.netbeans.org/DevFaqModuleObfuscation, but don't understand what they're saying.
Thanks for any input.
The FAQ you point to is for obfuscating NetBeans modules. This is quite a complicated use case, so I will assume that it is not the regular application you are interested in.
Very briefly: the obfuscation process changes the names of classes, methods and fields to make it more difficult to reverse engineer your application.
This causes some issues:
the JVM requires your application to have a public static void main( String args[] ) in a public class, so you must tell proguard not to change this name
if you are using any sort of introspection, you have to protect the relevant names from being changed
other cases, as explained in the manual
Additionally, proguard strips out unused code. If you have any classes that are used but not referenced directly, you have to -keep them as well.
The proguard documentation includes an example of how to obfuscate a simple application. Here is the example explained (with some less confusing names):
-injars application.jar # obfuscate all the classes in the named jars
-outjars obfuscated.jar # save all the obfuscated classes to the named jar
-libraryjars <java.home>/lib/rt.jar # these are all the libraries that the application uses
-printmapping obfuscation.map # save a file linking the original names to the obfuscated ones
# this helps understanding stack traces from the obfuscated application
# we need to keep our main class and the application entry point
-keep public class com.mycompany.Application {
public static void main(java.lang.String[]);
}
Unless you specify -dontshrink, proguard will remove any code not kept or not referenced from any kept code. So in the above configuration, any code not referenced (indirectly) by the main method will be removed.
Proguard includes an Ant task that can be used to integrate with the NetBeans workflow. I would suggest experimenting manually first though, without Ant, as that takes one of the complicating factors out of the process. Build your application jar with NetBeans and then try to obfuscate with the above configuration (fleshed out if necessary). Make sure to test the obfuscated application, as innumerable things can go awry. Once you have a working proguard configuration, try adding an Ant task to your build file to automate the obfuscation process within NetBeans.
Another solution than -dontskipnonpubliclibraryclasses is to use the same JDK for running proguard as you used for compiling the code in the JAR file.
For example, instead of
java -jar ../proguard3.8/lib/proguard.jar
use
/usr/local/jdk1.5.0/bin/java -jar ../proguard3.8/lib/proguard.jar
Jacob

Categories