I have two jar files with similar Util class names, but different method signatures.
In jar1, I have a main method which must use the method in Util class in jar1. The JVM is linking to Util class in jar2.
How to resolve this class conflict?
If both jar files are loaded into the same classloader then there is no way to determine which class will get loaded. The only way to handle this is to isolate them so only one of them is loaded into the classloader you are using.
You can set up a classloader and only load the jar you want to get the class from, but it is probably much easier to just make sure classes are unique on your path.
Normally one avoids that situation by using appropriate package names, such that they are different.
In extreme situations, where you dont have the choice to change the jar files,
there is the option "bootclasspath" where you can specify classes that gets loaded first.
Related
I have created a custom Java ClassLoader but I can't get the JVM to load it. I'm getting a ClassNotFoundException when I launch the application. The JAR that contains my code is added to the CLASSPATH as an argument to the JVM. Now I am wondering if I have the JAR in the correct place...do ClassLoaders get added here? I know that application code gets added to the CLASSPATH, but one could argue if a custom ClassLoader is application code or internal to the JVM. So, any ideas?
EDIT:
Ok, after thinking about this more, I think I may asking the JVM to do something circular. The ClassLoader I have created is a system class loader. These class loaders are the ones that search CLASSPATH for classes to load...but I have put the class loader itself there! So, if I'm correct, where do custom class loaders go?
If I have a java class and:
- I compile the class and include it in a jar, A
- compile separately the same class and include it in a different jar, B
(I know it's not politically right to do this...etc)
(the compilation is done against the same jdk, on the same machine)
If I put these two jars in the same war - can I get class loading problems?
Two ways to get into trouble:
Have two externally different classes by the same name, such that other classes that are compiled against one will not be valid referencing the second.
Have two identical copies of the class (or even the same copy) and manage (through one of several means) to load it twice with two different class loaders.
But having the same (from an external attributes standpoint) class twice in your classpath is not a problem -- the first one in the JAR search order will always be loaded.
No. You'll simply get the first copy it finds. If they're in the same package, you'll effectively never see that other class.
And it's not "politically" wrong to do this. It's fundamentally a bug.
I'm reading on class loading in Java.
Motivation
Assuming we have a classloader hierarchy that looks like this, I understand that classes loaded by First are not directly accessible by classes loaded by Second (and vice versa).
Bootstrap
|
System
|
Common
/ \
First Second
I also understand that a classloader checks with its parent class loader whether it can load the class and, if that is the case, delegates the loading to its parent.
Question
How do classloaders actually determine whether they can load some given class?
That differs depending on the implementation of the classloader. But all Classes a ClassLoader can load are retrieved by ClassLoader.findClass(String)
There are many implementations but the most common one is the URLClassLoader which loads classes from directories and jar files.
The classloader checks all classes (java class files) within your CLASSPATH path variable. If your class is found there, it exists, otherwise it doesn't.
So practically, your /src directory and all subdirectories (=packages) are scanned.
The classloader transforms the requested class name into a file name and then tries to find a "class file" of that name from a file system. As #poitroae notes, it uses the CLASSPATH variable, if set, as a starting place. Most IDEs and such extend this to include your working directories for the project.
I'm trying to write a decompiler for Java using reflection (all I need is the method signature information from a jar file passed in). I'm using a URLClassLoader to load classes from the jar file, and then pass that class on to my decompiler.
However, I've run into a problem. The jar I'm trying to read contains different versions of classes already loaded into my environment. So when I call
ClassLoader myClassLoader = URLClassLoader.newInstance(jars, null);
Class<?> classToDecompile = Class.forName(className, false, myClassLoader);
It returns not the class from my jar file, but the one that's already been loaded. Is there a way to load the class information for reflection only and get it from the jar passed in rather than from the JRE?
Edit:
The jar I'm trying to decompile contains classes in the java.lang package, which causes a security exception to be thrown:
java.lang.SecurityException: Prohibited package name: java.lang
ClassLoader.loadClass(String, boolean) - which URLClassLoader inherits - first checks for a previously-loaded class, and then, not finding any, checks with the parent class loader. You could override that method to bypass the check for a previously-loaded class. Not sure if you'd have to bypass the parent.
Mind you, this would be an evil class loader; you probably shouldn't use it for anything else.
You might also try reading the jar yourself, getting the contents of the class file (the byte codes), and calling ClassLoader.defineClass(name, byte[], int, int) yourself, supplying a unique name for the class. I think that's a better idea, actually.
Why wasting time when there is JAD? If you still want to achieve that you have to write your own class loader with child-first strategy.
I have a JAR-archive with java classes. One of them uses some resource that is embedded into the same JAR. In order to load that resource I use
MyClass.class.getResourceAsStream(myResourceName);
One thing that bothers me though is whether it is guaranteed that required resource will be loaded from within the same JAR. The documentation for "getResourceAsStream()" method (and corresponding ClassLoader's method) is not really clear to me.
What would happen if there's a resource with the same name located somewhere in JVM classpath before my JAR? Will that resource be loaded instead of the one embedded in my JAR? Is there any other way to substitute resource embedded in JAR?
Yes. The first matching resource found on the class path is returned, just like an executable search path. This is why resources are often "namespaced" by putting them in directories that mirror the package structure of the library or application.
This behavior may be slightly different in the presence of custom classloaders (say in OSGi), but for vanilla Java apps, it is the case.
It works much the same way as for finding class files. So first try the parent class loader (recursively) then do whatever the class loader implementation does to find files.
There is no checking of the immediate caller class loader (as ResourceBundle does - see section 6.3 of the Java Secure Coding Guidelines). However, you do need permissions to open the URL, as ClassLoader.getResourceAsStream just calls URL.openStream in the default implementation.
Specify the package. Assuming you use com.yourcompany.file it SHOULD be unique. (Unless someone WANTS to override your config file via the classpath.)
If you want to read the file only from a specific JAR you can open the JarFile and read it directly.