There’s 10 million articles and docs out there on what Java classloaders are, and how/*why* to write your own…but they all seem to be assuming some things that I can’t find a simple answer to!
I understand the job of the classloader: to read bytecode and construct an object from it. Different classloaders do this differently, etc.
But having never had to code against a class loader API in my own code, and never having to write one of my own, I’m having enormous difficulty understanding when a ClassLoader‘s own code actually fires.
For instance:
public static void main(String[] args) {
Fizz fizz = new Fizz();
fuzz.buzz();
}
Here, we have a Fizz object. Before a Fizz can be instantiated, we need a class loader to kick in and load Fizz.class into its cache. Where and when is this happening?!?! It’s not explicitly in my code so it must implicitly be somewhere in the JRE…?
Tangential to that question, if I write my own classloader, say, WidgetClassLoader and want to configure it to load either all my application’s classes, or perhaps just my Fizz.class, how do I “tie” this WidgetClassLoader into my application so that it knows which classloader to use? Would my code need to explicitly call this classloader or would it be implicit like the first example? Thanks in advance!
You question isn’t as trivial as you think now.
Your Fizz example:
When is Fizz loaded? This is defined in the JLS (Chapter 5.4: Linking). It does not define when Fizz is loaded, but it makes guarantees about the visible behavior. For the ‘when’ part, if Fizz can not be found, an Exception will be thrown from the first statement that accesses Fizz (Fizz fizz = new Fizz()). I’m pretty sure it will be the new Fizz() specifically in this case because the right side of the expression is evaulated first. In case you had written it like this:
In this case the Fizz fizz = null would already throw the Exception because its the first access to the Fizz class.
Who loads Fizz? When a class must be loaded, the classloader that ‘belongs’ to the code requiring the class is used to get the class. In the Fizz example this will be the classloader that loaded the class with the main method. Of course, the classloader may choose to delegate to its parent classloader if it can not load Fizz by itself.
How do I get the JVM to use my ClassLoader? There are two ways, explicitly or implicitly. Explicitly: you can load a class through your own classloader by calling its methods. Implcitly: when you execute code (meaning methods or initializers) from a class that was already loaded from your classloader and a class reference needs to be resolved in the process, your classloader will be automatically used because it is the classloader that loaded the code in the first place.