2. Fundamentals
1. Class loader delegation
a. The class loader delegation model is the graph of class loaders that pass
loading requests to each other.
b. The bootstrap class loader is the root of this graph.
c. Class loaders are created with a single delegation parent and looks for class
at:
i. Cache.
ii. Parent.
iii. Self.
3. Fundamentals
2. The parent class loader is always given the opportunity to load a class first.
3. Due to point #2, a classloader can only see classes loaded by itself or its
parent/ancestor classloaders and not by children.
4. The bootstrap class loader cannot be instantiated by java code.
4.
5. Fundamentals
5. The extension (standard extensions) class loader is responsible to load
classes from the extensions directory (jre/lib/ext).
6. The system (application)class loader is responsible for loading code from
the path specified by the CLASSPATH environment variable. This can be
returned by:
ClassLoader.getySystemClassLoader();
6. Phases of class loading
1. Loading
2. Linking
3. Initializing
7.
8. Phases explained
1. Loading phase
a. Consists of locating the required class file and loading in the
bytecode.
b. It gives a very basic memory structure to the class object.
c. Methods, fields and other referenced classes are not dealt with at this
stage.
9. Phases explained
1. Linking phase
a. Bytecode verification, the class loader performs checks on the bytecodes of
the class to ensure it is well formed and well behaved.
b. Class preparation, prepares the necessary data structures within each class
like fields, methods and implemented interfaces.
c. Resolving, the class loader loads all the other classes referenced by
particular class.
10. Phases explained
1. Initializing phase
a. Any static initializers contained within a class are executed.
Note: At the end of this phase, all static fields are given their default values.
11. Loading Types
Explicit loading
1. via, cl.loadClass() [cl is an instance of ClassLoader].
2. Class.forName().
When one of these methods is invoked, the class whose name is specified as an argument is loaded
by the class loader. If the class is already loaded, then a reference is simply returned; otherwise,
the loader goes through the delegation model to load the class.
12. Loading Types
Implicit loading
Occurs when a class is loaded as result of a reference, instantiation, or
inheritance (not via an explicit method call). In each of these cases, the
loading is initiated under the covers and the JVM resolves the necessary
references and loads the class.
14. Problems with class
loaders
3. When over riding loadClass().
If class loaders only use the standard delegation model, then there is no need to override the
loadClass() method. However, if a different model is required, then loadClass() must be
overridden, in which case there are special considerations that must be taken into account.
public Class loadClass(String name) throws ClassNotFoundException
{
return findClass(name);
}
Although this looks reasonable, a call to this method results in the
following exception:
Exception in thread "main" java.lang.NoClassDefFoundError:
java/lang/Object
Because the overridden loadClass() method never delegates to its
parent.
15. Problems with class
loaders
improved implementation
public Class loadClass(String name) throws ClassNotFoundException {
Class c = null;
try {
c = getParent().loadClass(name);
} catch (ClassNotFoundException e) {
}
if(c == null)
c = findClass(name);
return c;
}
16. Problems with class
loaders
Problem with serialization and GC
The collector examines the class loader data structures to determine which
classes are live -- that is, are not garbage collectable.
When the class loader is dereferenced, the classes that it loaded are not garbage collectable. This is
because there is a live reference to the serialized class from the ObjectStreamClass lookup table.
ObjectStreamClass is a primordial class and therefore is never garbage collected. The lookup
table is referenced from a static field in ObjectStreamClass and is kept in the class itself rather
than in an instance of it. As a result, the reference to serialized class exists for the lifetime of the
JVM, and the class thus cannot be garbage collected. Importantly, the serialized class has a
reference to its defining class loader, and so it cannot be completely dereferenced either.
17. Problems with class
loaders
Class loader deadlocks
A class loader deadlock occurs when two threads each own a lock on two different class loaders, and
both threads are waiting for the lock owned by the other thread. Both threads will wait indefinitely
for the lock on the other class loader, and so they become deadlocked.
18. Problems with class
loaders
Deadlock Scenario
Class Hierarchy:
class A extends B
class C extends D
ClassLoader Delegation Hierarchy:
Custom Classloader CL1:
directly loads class A
delegates to custom ClassLoader CL2 for class B
Custom Classloader CL2:
directly loads class C
delegates to custom ClassLoader CL1 for class D
Thread 1:
Use CL1 to load class A (locks CL1)
defineClass A triggers
loadClass B (try to lock CL2)
Thread 2:
Use CL2 to load class C (locks CL2)
defineClass C triggers
loadClass D (try to lock CL1)
19. Solution to deadlock
The Java SE 7 release includes the concept of a parallel capable class loader.
Loading a class by a parallel capable class loader now synchronizes on the
pair consisting of the class loader and the class name.
Thread 1:
Use CL1 to load class A (locks CL1+A)
defineClass A triggers
loadClass B (locks CL2+B)
Thread 2:
Use CL2 to load class C (locks CL2+C)
defineClass C triggers
loadClass D (locks CL1+D)
for more details: http://docs.oracle.com/javase/7/docs/technotes/guides/lang/cl-mt.html