I write myOwnClassLoader through extends the classLoader
and override its findClass method. And meet a interesting problem:
Here is the code segment:
public class MyClassLoader extends ClassLoader {
@Override
public Class<?> findClass(String name) {
byte[] bt = loadClassData(name);
return defineClass(name, bt, 0, bt.length);
}
private byte[] loadClassData(String className) {
...
}
public static void main(String[] args) throws ClassNotFoundException{
MyClassLoader myClassLoader = new MyClassLoader();
//Class<?> clazz = myClassLoader.findClass("com.classLoader.BMW");
Class<?> clazz = myClassLoader.loadClass("com.classLoader.BMW");
System.out.println(clazz.getClassLoader());//////////////////
}
}
when execute
Class<?> clazz = myClassLoader.findClass("com.classLoader.BMW");
the output meet my expectation: output:
com.classLoader.MyClassLoader@xxxxxx
but when execute
Class<?> clazz = myClassLoader.loadClass("com.classLoader.BMW");
the output go beyond my mind: output:
sun.misc.Launcher$AppClassLoader@xxxx
expect output
com.classLoader.MyClassLoader@xxxxxx
here is code segment of loadClass method in ClassLoader
Class<?> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
.....
I debug it and find when we invoke loadClass
at the first time the parent is sun.misc.Launcher$ExtClassLoader@6aa8ceb6 that is to say this reference is sun.misc.Launcher$AppClassLoader rather than com.classLoader.MyClassLoader@xxxxxx .
I search through internet and a blog define own classLoader tell that
it will set
AppClassLoader
as parent ofMyClassLoader
in default constructor.
I check it by
System.out.println(myClassLoader.getParent());
find the parent of MyClassLoader does be AppClassLoader how it achieve this, my default constructor do nothing and was this achieve in constructor method of its parent class ClassLoader? I read its parent constructor and still cant firgure out.
Anyway it seemd this cant explain why the this is AppClassLoader rather than MyClassLoader when we first invoke loadClass method.
And I guess it is because that *the classLoader of MyClassLoader is AppClassLoader
but it is just a intuition I have no gist.
Everything will be appreciated.
Well, it’s all documented:
ClassLoader()
constructor:
Creates a new class loader using the
ClassLoader
returned by the methodgetSystemClassLoader()
as the parent class loader.
loadClass(String)
:
Loads the class with the specified binary name. … Invoking this method is equivalent to invoking
loadClass(name, false)
.
loadClass(String,boolean-)
:
Loads the class with the specified binary name. The default implementation of this method searches for classes in the following order:
- Invoke
findLoadedClass(String)
to check if the class has already been loaded.- Invoke the
loadClass
method on the parent class loader. If the parent isnull
the class loader built-in to the virtual machine is used, instead.- Invoke the
findClass(String)
method to find the class.If the class was found using the above steps, and the
resolve
flag is true, this method will then invoke theresolveClass(Class)
method on the resultingClass
object.Subclasses of
ClassLoader
are encouraged to overridefindClass(String)
, rather than this method.
This is also mentioned in the class documentation of ClassLoader
:
The
ClassLoader
class uses a delegation model to search for classes and resources. Each instance ofClassLoader
has an associated parent class loader. When requested to find a class or resource, aClassLoader
instance will delegate the search for the class or resource to its parent class loader before attempting to find the class or resource itself. The virtual machine's built-in class loader, called the "bootstrap class loader", does not itself have a parent but may serve as the parent of aClassLoader
instance.
This logic ensures clean scoping, i.e. classes of the parent scope don’t refer to classes of a sub scope, and that there are no conflicts between classes of the same qualified name, but defined by different class loaders. Such classes may still exist in distinct scopes, but not in nested scopes. But class loaders are not enforced to follow this rule. The delegation model was introduced with Java 2.