类加载器就是加载class文件,获取二进制字节流。
类加载过程源码
步骤大概是
检查该类是否已经加载过了
如果有父类,就用父类loadClass
父类loadClass失败,就调用自己的findClass
package java.lang;
public Class<?> loadClass(String name) throws ClassNotFoundException {
return loadClass(name, false);
}
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
Class<?> c = findLoadedClass(name);//检查是否已经加载过了
if (c == null) {
long t0 = System.nanoTime();
try {
if (parent != null) {//有父就使用父类加载器
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
if (c == null) {//父类加载不到就是用findClass子类自己的加载器
// If still not found, then invoke findClass in order
// to find the class.
long t1 = System.nanoTime();
c = findClass(name);
// this is the defining class loader; record the stats
sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
sun.misc.PerfCounter.getFindClasses().increment();
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}
不使用双亲委派
重写loadClass方法,就可以实现
class MyClassLoader extends ClassLoader{
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
System.out.println("myClassLoader load");
return loadClass(name, false);
}
}
使用双亲委派
重写findClass方法就可以实现
class MyClassLoader extends ClassLoader{
@Override
public Class<?> findClass(String name) throws ClassNotFoundException {
System.out.println("myClassLoader load");
return loadClass(name, false);
}
}
网友评论