ExclassLoader
AppClassLoader
上图类关系出自sun.misc.Launcher类,可以看出ExclassLoader与 AppClassLoader都继承与URLClassLoader,而非继承Bootstrap ClassLoader
public class MyAppClassLoader {
private static class Test {
Test() {
System.out.println("Hello World!");
}
}
Launcher launcher = new Launcher();
public static void main(String[] args) throws ClassNotFoundException {
ClassLoader classLoader = MyAppClassLoader.class.getClassLoader();
System.out.println(classLoader);
System.out.println(classLoader.getParent());
System.out.println(classLoader.getParent().getParent());
}
}
"C:\Program Files\Java\jdk1.7.0_80\bin\java" "-javaagent:D:\idea\IntelliJ IDEA 2017.1.4\lib\idea_rt.jar=61577:D:\idea\IntelliJ IDEA 2017.1.4\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.7.0_80\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\jce.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\jfxrt.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\resources.jar;C:\Program Files\Java\jdk1.7.0_80\jre\lib\rt.jar;D:\ideaprojects\NewCoderTest\out\production\NewCoderTest" MyAppClassLoader sun.misc.Launcher$AppClassLoader@7b7035c6 sun.misc.Launcher$ExtClassLoader@3da997a null Process finished with exit code 0
ExclassLoader与 AppClassLoader都继承与URLClassLoade,而URLClassLoade实现抽象类ClassLoader。
分析Launcher源码
Launcher.class
public Launcher() {
Launcher.ExtClassLoader var1;
try {
//先创建ExtClassLoader
var1 = Launcher.ExtClassLoader.getExtClassLoader();
} catch (IOException var10) {
throw new InternalError("Could not create extension class loader");
}
try {
//由ExtClassLoader再去创建它的子类加载器,再讲将该类加载器置为Launcher的默认类加载器
this.loader = Launcher.AppClassLoader.getAppClassLoader(var1);
} catch (IOException var9) {
throw new InternalError("Could not create application class loader");
}
Thread.currentThread().setContextClassLoader(this.loader);
String var2 = System.getProperty("java.security.manager");
if(var2 != null) {
SecurityManager var3 = null;
if(!"".equals(var2) && !"default".equals(var2)) {
try {
var3 = (SecurityManager)this.loader.loadClass(var2).newInstance();
} catch (IllegalAccessException var5) {
;
} catch (InstantiationException var6) {
;
} catch (ClassNotFoundException var7) {
;
} catch (ClassCastException var8) {
;
}
} else {
var3 = new SecurityManager();
}
if(var3 == null) {
throw new InternalError("Could not create SecurityManager: " + var2);
}
System.setSecurityManager(var3);
}
}
ClassLoader.class
private static synchronized void initSystemClassLoader() {
if (!sclSet) {
if (scl != null)
throw new IllegalStateException("recursive invocation");
sun.misc.Launcher l = sun.misc.Launcher.getLauncher();
if (l != null) {
Throwable oops = null;
scl = l.getClassLoader();
try {
scl = AccessController.doPrivileged(
new SystemClassLoaderAction(scl));
} catch (PrivilegedActionException pae) {
oops = pae.getCause();
if (oops instanceof InvocationTargetException) {
oops = oops.getCause();
}
}
if (oops != null) {
if (oops instanceof Error) {
throw (Error) oops;
} else {
// wrap the exception
throw new Error(oops);
}
}
}
sclSet = true;
}
}
追踪到最后由该类进行调用 (看注释可以得出,作为默认加载器被调用)
@CallerSensitive
public static ClassLoader getSystemClassLoader() {
initSystemClassLoader();
if (scl == null) {
return null;
}
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkClassLoaderPermission(scl, Reflection.getCallerClass());
}
return scl;
}
看ClassLoader.class中的loadClass方法,探究类加载原理
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
//getClassLoadingLock方法,通过类名获取
synchronized (getClassLoadingLock(name)) {
// 检查该类是否已经被加载过
Class c = findLoadedClass(name);
if (c == null) {
//计时,输出纳秒级别时间
long t0 = System.nanoTime();
try {
//由此可见BootstrapClassLoader并不是ExtClassLoader加载器的父加载器,仅仅只是在通过父加载优先行不通的情况下,才会去找BootstrapClassLoader
if (parent != null) {
//先查找父类加载器,false表示
c = parent.loadClass(name, false);
} else {
//查找BootstrapClass,找不到返回null
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
if (c == null) {
// 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;
}
}
private final ConcurrentHashMap<String, Object> parallelLockMap;
通过类名,如果paralleLockMap这个ConcurrentHashMap为空,这返回ClassLoader,否则通过putIfAbsent源码可以看到,该方法如果一个HashEntry中能够找到该key对应value值则返回该value,
如果找不到,则返回null,则返回Object
protected Object getClassLoadingLock(String className) {
Object lock = this;
if (parallelLockMap != null) {
Object newLock = new Object();
//通过putIfAbsent源码可以看到,该方法如果一个HashEntry中能够找到该key对应value值则返回该value,如果不能找到,则返回null,下面会分析ConcurrentHashMap中的该源码
lock = parallelLockMap.putIfAbsent(className, newLock);
if (lock == null) {
lock = newLock;
}
}
return lock;
}
protected final Class<?> findLoadedClass(String name) {
if (!checkName(name))
return null;
return findLoadedClass0(name);
}
//native关键字说明其修饰的方法是一个原生态方法,方法对应的实现不是在当前文件,而是在用其他语言(如C和C++)实现的文件中。
private native final Class findLoadedClass0(String name);
总结:由上的代码分析可以分析出loadClass加载类的过程,以及对BootstrapClassLoader的误解。