可以通过ClassLoader.getSystemClassLoader()方法获取系统类加载器,下面进入到ClassLoader的该方法中查看系统类加载器如何被创建。
1、通过initSystemClassLoader()方法来初始化系统类加载器
public static ClassLoader getSystemClassLoader() {
initSystemClassLoader(); //初始化系统类加载器
if (scl == null) { //scl是ClassLoader类的成员变量,表示系统类加载器
return null;
}
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkClassLoaderPermission(scl, Reflection.getCallerClass());
}
return scl;
}
2、在initSystemClassLoader()方法中, 首先会初始化Launcher类,然后调用Launcher的getClassLoader()方法获取系统类加载器。
private static synchronized void initSystemClassLoader() {
if (!sclSet) { //sclSet表示一旦系统类加载器被初始化,就设置为true,
if (scl != null)
throw new IllegalStateException("recursive invocation");
//获取Launcher实例,这里使用单例模式获取
sun.misc.Launcher l = sun.misc.Launcher.getLauncher();
if (l != null) {
Throwable oops = null;
//通过Launcher的getClassLoader获取系统类加载器,Launcher类中维护了一个成员变量叫
//classLoader,表示系统类加载器
scl = l.getClassLoader();
try {
//判断是否有自定义类加载器,上面已经获取了系统类加载器,这里判断如果有
//自定义类加载器,就将scl赋值为自定义类加载器
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;
}
}
3、SystemClassLoaderAction类的实现
class SystemClassLoaderAction
implements PrivilegedExceptionAction<ClassLoader> {
private ClassLoader parent; //成员变量,表示系统类加载器
SystemClassLoaderAction(ClassLoader parent) {
this.parent = parent; //将传入的系统类加载器赋值给变量
}
public ClassLoader run() throws Exception {
//从系统属性中获取java.system.class.loader的值,该值是一个类加载器的全限定名,代表系统类
//加载器,默认java.system.class.loader属性为null
String cls = System.getProperty("java.system.class.loader");
//若cls为空,说明用户没有在代码中自定义累加器作为系统类加载器,则返回从
//Launcher.getClassLoader获取的系统类加载器
if (cls == null) {
return parent;
}
//如果不为空,根据全限定类名使用Class.forName()去加载并获取到含有ClassLoader类型参数的
//构造函数;forName的三个参数是:
//cls:java.system.class.loader定义的类加载器的全限定名
//true:表示初始化该类加载器,false表示不初始化该类加载器
//parent:是系统类加载器,表示使用系统类加载器加载器cls类
Constructor<?> ctor = Class.forName(cls, true, parent)
.getDeclaredConstructor(new Class<?>[] { ClassLoader.class });
//通过反射创建这个自定义类加载器的实例,并将系统类加载器(parent)传入,作为其父类
ClassLoader sys = (ClassLoader) ctor.newInstance(
new Object[] { parent });
//将线程上下文类加载器设置为这个自定义类加载器
Thread.currentThread().setContextClassLoader(sys);
return sys;
}
}