All topics
memory management
advanced

Class Loaders

Load .class bytecode into the JVM on demand, organized in a parent-delegation hierarchy.

A class loader is the part of Java that finds a .class file and turns it into a class your program can use. Every class you write, and every class in the JDK, is loaded by one.

A library system. You ask the local branch (App loader); if they don't have it, they ask the regional library (Platform), then the national archive (Bootstrap). Books are only printed locally if no one upstream has them.

Key Concepts

1
You rarely think about this until something breaks. When it does, the error messages are some of the most confusing in Java. This page explains the model so those messages start making sense.
2
There are three loaders, and they form a chain. The bootstrap loader is first. It loads the core classes such as String and Object. Next is the platform loader, for the rest of the JDK. Last is the application loader, which loads your own code from the classpath. Each loader has a parent. The chain ends at the bootstrap loader.
StringObject
3
A loader asks its parent first. When your code needs a class, the application loader does not look for it straight away. It asks its parent. That parent asks its own parent. Only when nobody above can find the class does the original loader try. This is called delegation.
4
Delegation exists to protect the core classes. Suppose you create your own class called java.lang.String. Without delegation, your version might get loaded instead of the real one. With it, the bootstrap loader answers first and your version is ignored.
java.lang.String
5
A class is identified by its name plus its loader. This is the part that surprises people. The same .class file, loaded by two different loaders, produces two different types. Java treats them as unrelated. Casting one to the other fails.
.class
6
The error looks impossible when you first see it: a ClassCastException saying it cannot cast com.example.User to com.example.User — the same name on both sides. That message means two loaders are involved, not that something is wrong with your code.
ClassCastExceptioncom.example.User
7
Loading happens in three phases, and they are separate. First, loading: Java reads the bytes and creates the class. Second, linking: it checks the bytecode is valid and sets static fields to their default values (0, null). Third, initialisation: your static blocks run and static fields get their real values.
0nullstatic
8
The gap between phases matters. A class can be loaded long before its static block runs. The block runs on first real use, such as creating an instance or calling a static method.
static
9
Frameworks use custom loaders to keep code apart. An application server gives each deployed application its own loader. Two applications can then use different versions of the same library without clashing. Plugin systems work the same way.
10
There is a cost. A loader keeps every class it loaded alive in memory. If something still holds a reference to an old loader, none of its classes can be freed. That is why redeploying an application several times can slowly exhaust memory.
11
What the interviewer is probing.1. "Explain the delegation model." Probing: whether you know which way requests travel. Stalls: "Loaders load classes." Moves up: a loader asks its parent first, and this is what stops your code from replacing java.lang.String.
java.lang.String
12
2. "Can two classes have the same name?" Probing: how Java identifies a class. Stalls: "No." Moves up: yes, if two loaders loaded them. The sign is a ClassCastException naming the same class twice.
ClassCastException
13
3. "ClassNotFoundException or NoClassDefFoundError?" Probing: whether you can tell them apart. Stalls: "Both mean the class is missing." Moves up: the first comes from code that looked a class up by name. The second means the class was there when you compiled, but is missing or failed to initialise now.
14
4. "Why does redeploying repeatedly run out of memory?" Probing: what a loader holds onto. Stalls: "A memory leak." Moves up: each deployment has its own loader, and a loader keeps all its classes alive. One leftover reference keeps the whole set in memory.
15
5. "When would you write your own loader?" Probing: whether you know what it is for. Stalls: "For flexibility." Moves up: to isolate plugins or tenants that need different versions of a library, or to load classes from somewhere other than the classpath.
16
  The chain and what each loader owns
17
    Bootstrap (native)   java.base -- String, Object, Integer
         ^
    Platform             JDK modules outside the core
         ^
    Application          your classpath / module path
         ^
    Custom (optional)    plugin, web app, tenant isolation
18
    Lookup order: ask the PARENT first, all the way up; try
    yourself only if nobody above could load it.
19
  Phases
20
    1. Loading         read bytes, create the Class object
    2. Linking
         verify        bytecode is well-formed and safe
         prepare       static fields get DEFAULT values (0, null)
         resolve       symbolic references resolved (may be lazy)
    3. Initialisation  static initialisers run, statics assigned
                       -- triggered by FIRST ACTIVE USE, not by
                          loading
21
  Error decoder
22
  ClassNotFoundException        explicit lookup (Class.forName,
                                loadClass) failed -> missing jar,
                                wrong name
  NoClassDefFoundError          present at compile time, absent or
                                unloadable now -- OR its static
                                initialiser threw earlier
  ExceptionInInitializerError   the static initialiser threw, this
                                time (the informative one)
  UnsupportedClassVersionError  class file newer than the JVM
                                (e.g. compiled for 21, running 17)
  LinkageError / ClassCastException naming the same class twice
                                same bytes, two loaders