Java is there a way to load a class that has been already loaded by the System ClassLoader by a different one?

StackOverflow https://stackoverflow.com/questions/9220561

Pregunta

(Terrible Title, I know)

The best way to explain this, is that I need to load some classes that will be loaded at Runtime from a URLClassLoader, by these classes have references to instances of classes that are already loaded by the System ClassLoader and they can't be reloaded because of some other issues.

Also, I am willing to change around my code so I can load classes from a jar in the class path with the System ClassLoader, but I haven't been able to do that.

¿Fue útil?

Solución

No. Every classloader has the bootstrap classloader as an ancestor, and trying to load a class that is already defined in a classloader will just result in use of the ancestor's version. This is intentional to prevent java.lang.Object and other intrinsics from being redefined.

From the javadoc for ClassLoader:

The ClassLoader class uses a delegation model to search for classes and resources. Each instance of ClassLoader has an associated parent class loader. When requested to find a class or resource, a ClassLoader instance will delegate the search for the class or resource to its parent class loader before attempting to find the class or resource itself. The virtual machine's built-in class loader, called the "bootstrap class loader", does not itself have a parent but may serve as the parent of a ClassLoader instance.

You may be able to define a custom classloader that exposes defineClass without it being called by findClass and avoid the delegation that happens in findClass, but I would not rely on defineClass(className, bytes) working as intended on all JVMs when parent.findClass(className) exists.

Otros consejos

Yes, you can define another classloader and load the class.

As per spec

"At run time, a class or interface is determined not by its name alone, but by a pair: its fully qualified name and its defining class loader. Each such class or interface belongs to a single runtime package. The runtime package of a class or interface is determined by the package name and defining class loader of the class or interface."

Yes. But you need to be slightly careful because the default parent class loader is the system class loader, not the boot class loader. I suggest using java.net.URLClassLoader.newInstance(myURLs, null). If you want to be flash, get the parent class loader from the system class loader, and that will include extension classes.

(Note, terminology is a bit twisted because it dates from before Java2 when classpath included what is now bootclasspath (a pain for installers). So the system classes are not loaded by the system class loader.)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top