Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java ClassLoader and Dependency Resolution

Can someone clarify that the role of a ClassLoader is not only to load an individual class, but also its dependencies? And if so, what exactly does the entire process entail? I'm looking for implementation detail if at all possible.

For example, at some point, bytes are going to have to be read in from somewhere (a network or filesystem location), and file system locations are going to have to be calculated on the basis of a classes canonical name and a foreknowledge of class paths available to the JVM- how does an individual ClassLoader try to locate a file over potentially multiple class-paths? Where does it get this information from? Also, at what point are a class files bytes verified and its dependencies examined for availability?

As much detail as possible would be appreciated :)

like image 659
VLostBoy Avatar asked Dec 17 '10 18:12

VLostBoy


1 Answers

ClassLoading is a very complex subject. The ClassLoader and Java security model are inextricably tied together. Essentially the JVM loads classes on demand. When there is a hierarchy of classloaders, the JVM attempts to resolve the class as far down the chain as possible. In short, if the class is defined in the "boot" classloader and in an application defined class loader, it will always use the version in the boot classloader.

Within a classloader, such as the URLClassLoader, the search order is the order in which you've told it to look. Essentially the array of URLs you told it had classes will be searched from the first entry to the last.

When the class that you defined references another class, that class is also resolved using the same algorithm. But here's the catch: it only resolves it relative to where it was found. Let's take the scenario where the class SomeCoolThing is in the boot classloader, but depends on SomeLameThing, which is in an application defined classloader. The process would look like this:

App-ClassLoader: resolveClass("SomeCoolThing")
    parent->resolveClass("SomeCoolThing")

Boot-ClassLoader (the ultimate parent): resolveClass("SomeCoolThing")
    SomeCoolThing needs SomeLameThing
    resolveClass("SomeLameThing") // Can't find SomeLameThing!!!!

Even though SomeLameThing is in the classloader where you requested SomeCoolThing, SomeCoolThing was resolved in a different classloader. That other classloader has no knowledge of the child classloader, and tries to resolve it itself and fails.

I had a book a long time ago that covered the Java ClassLoaders in really good depth, and I recommend it. It's Java Security by O'Reilly Media. It will answer every question you never wanted to know, but still need to, when dealing with ClassLoaders and how they work.

like image 76
Berin Loritsch Avatar answered Sep 29 '22 17:09

Berin Loritsch