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.
Related
Today I started learning Java.
I saw that package automatic gets included in .Java file.
I was wondering if it always need to be included?
Consider specify a common package for all the types within a same project.
In Java is common to start a project with a specific package setting. A package creates a namespace to disambiguate the types that it includes, to play nicelly with other projects that may or may not be in the same classpath. Normally, the package is bound to a URL of the project.
Think of Java packages like C++ namespaces.
A huge project/product written in Java can depend on lots and lots of projects, each described in a different package.
Organizations like Apache have lots of projects, organized under a common package pattern: org.apache.<<name_of_the_project>>.
Consider starting your project with a package named: com.user3552670; or something like your personal site, so persons that will consume your project can relate to the creator.
Yes and no.
It's used to specify the package of the class, read more here.
You could create a class without a package, but your code will look bad..
They exists to avoid conflicts, example between your code and default java package.
If packages doesn't exists, you can't create a class named ArrayList because already exists in Java.
Some IDEs force the fact that, if your .java file is in com/a/b/c folder his package should be com/a/b/c (If i don't remember wrong, IntellIJ IDEA do that)
Yes and no.
It must be there, but the IDE takes care of it (I don't use Netbeans, but I'd bet that it can do it, too). When moving files between packages, it has to be updated, but again, the IDE does it all.
Can I use ClassLoader's definePackage to override some packages from inside a jar?
For example, the application currently contains "javax.xml.bind" from abc.jar. If I call ClassLoader.definePackage(def.jar), in which the def.jar contains another version of javax.xml.bind, can I replace the classpath for the entire application to point to that of def.jar? Thanks.
No, you definitely can not use ClassLoader.definePackage to "override" some packages from inside a jar.
If I understand correctly, you want to make your JVM load any class under javax.xml.bind from def.jar while all other ones from abc.jar. In this case you can (in my personal order of preference):
1) Put def.jar before abc.jar in the CLASSPATH. This requires that no class you want loaded from abc.jar is present in def.jar.
2) Unzip def.jar, abc.jar, or both, and remove any conflicting classes so it is really irrelevant which jar comes first in the CLASSPATH. Then re-zip them. Or you can do this only on one jar and put it before the other.
3) Use a configurable classloader (sorry, no public domain one that I know of; let me know if you find one). This could be an interesting topic for an OS project, except that several initiatives with similar (but much broader) objectives are already ongoing, some at the core of the language.
4) Create a classloader for this purpose, probably extending the default one.
In Java, I recently faced a case where I was getting two different jars that each defined a class. The problem was that one of these jars was out of date and the class in question was missing a method that existed in one jar and not the other.
So, I was getting an error that the method being used in the code couldn't be found. I was eventually able to resolve this by removing the old jar, so that it imported the correct one.
Many people used this same code (with the same two, conflicting, imported jars) and did not have this problem. So, they must have been importing the up-to-date jar.
My question is this: What caused me to import one jar over another? What logic determines which is "used"?
Thanks!
Based on the order. The first one will be used and the second one will start causing issues.
Make sure you don't include different versions of the same class. You may encounter weird bugs because of that.
The class path determines the order in the same way that you PATH determines which program you will run if you have multiple programs witht he same name.
You can get weird bugs, but most of the time having multiple versions of a jar is not a problem (meaning it could have been there for a while and is difficult to test)
Look at your CLASSPATH. What order do your jar files appear in on the CLASSPATH?
If you're not explicitly setting the CLASSPATH variable (or command-line arguments or however your framework finds classes), then set it in such a way that the classes you want appear earlier.
I am building java jar file using ant. I need to include additional jars using "zipfileset src="xxx.jar" "zipfileset src="yyy.jar" and both xxx.jar and yyy.jar have the classes with the SAME fully-qualified class names. So the resulting jar file has duplicate class names. What are the possible implications of having duplicates?
Thank you.
If they're duplicate implementations, nothing–it wouldn't matter which is loaded.
If not, you're at the mercy of class load order, and may get a different version than you want.
It is specified that classpath entries will be searched in the order listed (as per this classpath doc). but that's only relevant if you're in complete control of classpath creation (unlike in a web app, for example).
(With the caveat that classpath wildcarding makes the order non-deterministic.)
In general this situatioin is highly non recommended
and should be avoided.
Jars in java are just containers for your class files. java uses classloaders that look at the classpath and load class files from there. so if you have 2 jars A.jar and B.jar that have the same class x.y.Foo inside, the class from the jar that comes first in the classpath will be loaded.
So, if your classpath is A.jar,B.jar (in this order) the class Foo from A.jar will be used in runtime.
This inconsistency can lead to very hard-to-fix bugs from my experience
whats mean duplicated? it's obvious that you can not have 2 classes with the same name in the same package (even your project will not compile), but if you mean that you have 2 classes with the same name in different packages that's "is ok".
I agree with Dave.
Can you separate them by namespace to avoid the pitfalls he suggests?
Another answer which I don't see discussed here is that if you plan on signing your jars, aars, apks then it signjar will complain that you have duplicate entries
jarsigner: unable to sign jar: java.util.zip.ZipException: duplicate entry: com/foo/bar/baz.java
Suppose I have have a java project myProject and am using an external library jar (someJar.jar), which has a class com.somepackage.Class1.class.
Now I find an updated version of Class1.java which fixes a bug in the original jar.
I include the new Class1.java in my source code under package com.somepackage
When I build the project (e.g., using Netbeans), there is a dist\myProject.jar which contains the classcom.somepackage.Class1.class and a dist\lib\someJar.jar which also contains a class with the same name.
When I run the file (e.g, using java -jar dist\myProject.jar), the new version of Class1.class is used (as I want).
How does Java decide which class file to run in case of such duplicates? Is there any way I can specify precedence ?
Is there any 'right' way to avoid such clashes?
In Proguard, when I try to compress my code, I get a duplicate class error. How do I eliminate this?
Java decides which one to use based on the order of the classpath. List yours first and you'll be fine.
The "right" way would be to fix the orignal source, but sometimes that's not always an option.
I haven't used ProGuard, but I have re-jarred libaries before that had duplicate classes. The solution in my case was to tell Ant to ignore duplicate classes. I would assume ProGuard would have that support too.
Can you not create an updated jar file which contains the bug fix? It's going to make things a lot simpler if you don't have two versions of the same fully-qualified class around.
1) Updated Jar is a better solution.
2) Use a different class name. Is there a reason, why you want to use the same class name and same packing? I don't think there is a reason.
3) create a wrapper/ proxy class, that encapsulate all the calls to the jar and you can decide to call this new class that fixes the bug ( provided it has a different name and packaging)