getSystemClassLoader()方法源代码解析
public static ClassLoader getSystemClassLoader() {
initSystemClassLoader();
if (scl == null) {
return null;
}
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkClassLoaderPermission(scl, Reflection.getCallerClass());
}
return scl;
}
从上文可以看出调用了initSystemClassLoader方法。scl是一个ClassLoader对象的引用,下面是安全部分的代码,先跳过。那么我们就来看看initSystemClassLoader()方法做了什么事情。
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;
}
}
sclSet是一个布尔类型的对象,表示scl是否被设置值。所以做了一个双重判断,sclSet为false的时候,scl应该是为空的。否则调用sun.misc.Launcher.getLauncher()方法获得Launcher的一个引用。我们待会再看这个方法。假设方法返回了一个Launcher对象,将Launcher中的ClassLoader成员变量赋值给了scl。并且在权限安全的情况下,new了一个SystemClassLoaderAction,传入了scl。最后把sclSet赋值为true。这个方法中有两个方法需要讲解,一个是sun.misc.Launcher.getLauncher()。另外一个是new SystemClassLoaderAction(scl)
我们先来看看sun.misc.Launcher.getLauncher()
……
private static Launcher launcher = new Launcher();
……
public static Launcher getLauncher() {
return launcher;
}
public Launcher() {
Launcher.ExtClassLoader var1;
try {
var1 = Launcher.ExtClassLoader.getExtClassLoader();
} catch (IOException var10) {
throw new InternalError("Could not create extension class loader", var10);
}
try {
this.loader = Launcher.AppClassLoader.getAppClassLoader(var1);
} catch (IOException var9) {
throw new InternalError("Could not create application class loader", var9);
}
Thread.currentThread().setContextClassLoader(this.loader);
String var2 = System.getProperty