@CallerSensitive
public static ClassLoader getSystemClassLoader() {
initSystemClassLoader();
if (scl == null) {
return null;
}
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkClassLoaderPermission(scl, Reflection.getCallerClass());
}
return scl;
}
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;
}
}
sun.misc.Launcher l = sun.misc.Launcher.getLauncher(); 就在这里使用,但是当我new 一个自定义classLoader的时候,其实这个scl变量已经存在值,这是因为这个是静态变量,在我调用之前已经有别的类调用过了,因此这里有值。
下面是一些练习出现的情况:
出现以下异常:
Exception in thread "main" java.lang.ClassCastException: com.cong.ClassLoaderLK cannot be cast to com.cong.ClassLoaderLK
看起来两个对象一样,为什么不能转换呢,因为加载的时候我把双亲委派的方式破坏了,其实这个两个类是不同的class实例化出来的,虽然是同一份字节文件,但是用了两个不同的classloader来加载就会出现这个问题
我的练习代码:
package com.cong;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.WritableByteChannel;
public class ClassLoaderLK extends ClassLoader {
/**
* @param args
*/
public static void main(String[] args) {
// this.class.getSystemClassLoader();
String ext = "java.ext.dirs";
System.out.println("java.ext.dirs :\n" + System.getProperty(ext));
String cp = "java.class.path";
System.out.println("java.class.path :\n" + System.getProperty(cp));
ClassLoader currentClassloader = ClassLoaderLK.class.getClassLoader();
ClassLoader c = sun.misc.Launcher.class.getClassLoader();
System.out.println(c);
c = System.class.getClassLoader();
System.out.println(c);
c = AbcBean.class.getClassLoader();
System.out.println(c);
//sun.misc.Launcher$ExtClassLoader@2259e205
//这个地址是你的classpath
String pp = "E:\\demo\\用 SpringMVC+MyBatis 来搭建网站\\源码\\demo\\target\\classes\\";
ClassLoaderLK cl = new ClassLoaderLK(currentClassloader, pp);
System.out.println();
System.out.println("currentClassloader is " + currentClassloader);
System.out.println();
String name = "com.cong.AbcBean.class";
// String name = "java.util.Arrays.class";
name = "com.cong.AbcBean";
String name2 = "com.cong.ClassLoaderLK";
// name = "java.util.Arrays";
try {
//Class<?> loadClass = cl.loadClass(name);
AbcBean abc = new AbcBean();
AbcBean abc2 = new AbcBean();
abc.greeting();
//System.out.println(abc.greeting());
//Class<?> loadClass = cl.findClass(name);
Class<?> loadClass = cl.findClass(name);
System.out.println(loadClass.getClassLoader());
Class<?> loadClass2 = cl.findClass(name2);
Constructor ccc =loadClass2.getDeclaredConstructor(new Class[]{String.class});
System.out.println(ccc.newInstance(new Object[]{pp}).getClass().getClassLoader());
Object o = ccc.newInstance(new Object[]{pp});
System.out.println(o.getClass().getClassLoader());
Method m = o.getClass().getMethod("findClass", String.class);
Object oo = m.invoke(o, name);
System.out.println(oo.getClass().getClassLoader());//这里不明白为什么为null
System.out.println(oo.getClass().getClassLoader().getParent());
// ll.getClass().getClassLoader()
// ClassLoaderLK ll = (ClassLoaderLK)loadClass2.newInstance();
//Class<?> loadClass2 = cl.findClass(name);
//loadClass = ll.findClass(name);
//System.out.println("===" + (loadClass == loadClass2));
Object object = loadClass.newInstance();
System.out.println(object.getClass().getClassLoader());
System.out.println(object.getClass().getClassLoader().getParent());
System.out.println(object.getClass().getClassLoader().getParent().getParent());
System.out.println("abc==abc2" + (abc.getClass() == abc2.getClass()));
System.out.println("abc==object" + (abc.getClass() == object.getClass()));
System.out.println("abcClassLoader=" + abc.getClass().getClassLoader());
System.out.println("objectClassLoader=" + object.getClass().getClassLoader());
// URLClassLoader
System.out.println("123=" + object.getClass());
// AbcBean ss = (AbcBean) object; // 无法转换的 (1)
// ss.greeting(); (1)
System.out.println();
System.out.println(" invoke some method !");
System.out.println();
Method method = loadClass.getMethod("greeting");
method.invoke(object);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private ClassLoader parent = null; // parent classloader
private String path;