Alright then,
A common application has 3 standard classloaders:
- Bootstrap Classloader
- Extensions Classloader
- System-Classpath Classloader
So far, so good. Now, this works for a single application running alone and free.
But what happens when you say J2EE? You have multiple applications running on the same place, so you have to figure out a way to prevent them from stumbling on each other. That's where these extra classloaders come into play.
Think about a server instance. There's a JBoss with two deployed EARs. What would happen if there were to be conflicting classes between applications? They're ok on their own particular context but as a whole they're inconsistent.
These extra classloaders are introduced in an application-wise way to ensure the isolation between them. Classloaders below System-Classpath Classloader recognize a class only if it is specified in the manifest file for one of its childs.
In J2SE, the three basic classloaders work in a parent-child relationship based on three principles:
- Delegation: If a class is not loaded (cache), the request is delegated to its parent. This goes on until the top of the hierarchy (Bootstrap classloader) who loads basic J2SE related classes (i.e.
Integer
, ArrayList
, amongst others). This is what you reference in your question: A classloader delegates the loading until the top of the hierarchy, then each classloader tries to load the class if its parent couldn't find it, until someone loads it. Otherwise: ClassNotFound.
- Visibility: Classes loaded by a parent classloader are visible to its children, not the other way around.
- Uniqueness: If a parent classloader loads a class, a children will never reload it.
In Java SE, a classloader delegates the classloading to its parent classloader and then tries to load the class itself.
True, due to the principles explained above.
There's no determined classloader structure in J2EE (a vendor has "poetic license" to implement it), but they kind of follow a hierarchy. In this case, the System-classpath classloader loads the main application: The server. The server libraries (its classes, more specifically) are available, then, to every application due to the visibility principle.
Down there, the applications have particular classloader structures, but as a whole they are different children of the System-classpath classloader. Each application loads its related and particular classes (both application and libraries).
The loading here is not propagated to the parents outside the application context. Why? because if the System-classpath classloader were to load the applications as usual, the class of every application would be visible to others due to the visibility principle, completely breaking the isolation between themselves. So:
However, In Java EE, a classloader first tries to load the class itself and then delegate the classloading of that class to its parent classloader.
This is partly true, but I'd rather limit this affirmation to the context of an application and leave out the Java related classes, that are indeed loaded by the top level classloaders.
Long story short: It's not a straightforward process but I wouldn't go as far as to say J2EE handles the classloading the opposite way around of J2SE.