3

(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.

Josh
  • 83
  • 10

3 Answers3

3

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.

Mike Samuel
  • 118,113
  • 30
  • 216
  • 245
  • Nothing forces any particular implementation/subclass of ClassLoader to actually implement this behavior. – bmargulies Feb 09 '12 at 23:31
  • @bmargulies, I was under the impression that `resolveClass` is final, that implements the delegation, and that is a gatekeeper to all production of loaded, initialized `Class` instances. – Mike Samuel Feb 09 '12 at 23:34
  • @bmargulies, I looked at section 12.3 again, and I don't see any alternate linkage mechanism. Let's say I successfully define `java.lang.Object` in my custom `ClassLoader` and then I want to load another class whose bytecode contains symbolic references to `java.lang.Object`. What alternative link mechanism is there that will cause `java.lang.Object` in that second class to resolve to a `java.lang.Object` that is different from the parent classloader's version? – Mike Samuel Feb 10 '12 at 01:54
  • @bmargulies, I have low confidence in my answer as written since I have never worked on a production JVM, and you have a good point about the "may", but I can't find any clear language in the spec or docs that weighs one way or another. – Mike Samuel Feb 10 '12 at 02:59
1

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."

kosa
  • 65,990
  • 13
  • 130
  • 167
1

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.)

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305