目录
public class TestClassLoader extends ClassLoader {
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
System.out.println("进入自定义加载器");
byte[] data = loadClassData();
return this.defineClass(name, data, 0, data.length);
}
/**
* 读取编译好的.class文件返回对应的字节数组
*/
private byte[] loadClassData() {
InputStream in = null;
byte[] data = null;
ByteArrayOutputStream baos = null;
try {
in = new FileInputStream(new File("/Users/wangbo/Downloads/code/my/classfile/bobo.class"));
baos = new ByteArrayOutputStream();
int ch = 0;
while (-1 != (ch = in.read())) {
baos.write(ch);
}
data = baos.toByteArray();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
in.close();
baos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return data;
}
public static void main(String[] args) throws Exception {
//不注释下面的bobo类,因为会使用appclassload加载bobo.class,所以虽然下面二个类加载器实例不是同一个命名空间下,但是class只会被加载一次
//注释bobo类,系统类加载器找不到bobo会调用我自定义的类加载器,二个不同的命名空间,class会被二个加载器都加载一次
//自下而上树形查找是否加载过
TestClassLoader testClassLoader = new TestClassLoader();
//loadClass并不会导致对该类的初始化
Class<?> calss = testClassLoader.loadClass("com.notecode.test.bobo");
Object o = calss.newInstance();
System.out.println("calss对象:" + calss.hashCode());
System.out.println("实例对象:" + o);
System.out.println("类加载器:" + o.getClass().getClassLoader());
TestClassLoader testClassLoader2 = new TestClassLoader();
Class<?> calss2 = testClassLoader2.loadClass("com.notecode.test.bobo");
Object o2 = calss2.newInstance();
System.out.println("calss对象:" + calss2.hashCode());
System.out.println("实例对象:" + o2);
System.out.println("类加载器:" + o2.getClass().getClassLoader());
}
}
//class bobo{
//
//}
[类中对类的主动使用触发的类加载]
public static void main(String[] args) throws Exception {
//运行会报错 Caused by: java.lang.ClassNotFoundException: com.notecode.test.bobo
//错误分析:
// 根据双亲委派机制,bobo1.class的文件路径在classpath下,所以是系统类加载器去加载
// bobo1的构造方法中调用了bobo类,造成其主动使用,所以会触发加载
// 会使用加载bobo1的系统类加载器去加载bobo,所以报错
TestClassLoader testClassLoader = new TestClassLoader();
Class<?> calss = testClassLoader.loadClass("com.notecode.test.bobo1");
Object o = calss.newInstance();
System.out.println("calss对象:" + calss.hashCode());
System.out.println("实例对象:" + o);
System.out.println("类加载器:" + o.getClass().getClassLoader());
}
}
class bobo1{
bobo1(){
//存在在磁盘外的class文件
new bobo();
System.out.println("bobo1构造器");
}
}
[不同命名空间类的可见性]
public static void main(String[] args) throws Exception {
//运行结果:
// calss对象:500977346
//实例对象:com.notecode.test.bobo@133314b
//类加载器:com.notecode.test.TestClassLoader@9807454
//sun.misc.Launcher$AppClassLoader@18b4aac2
//Exception in thread "main" java.lang.NoClassDefFoundError: com/notecode/test/bobo
//错误分析
//命名空间的导致的可见性问题
//因为加载bobo1的是系统类加载器,其父是看不见子所加载的类
//小技巧:类中创建和查找其他类的时候,都用的是当前类的命名空间
TestClassLoader testClassLoader1 = new TestClassLoader();
Class<?> calss1 = testClassLoader1.loadClass("com.notecode.test.bobo");
Object o1 = calss1.newInstance();
System.out.println("calss对象:" + calss1.hashCode());
System.out.println("实例对象:" + o1);
System.out.println("类加载器:" + o1.getClass().getClassLoader());
TestClassLoader testClassLoader = new TestClassLoader();
Class<?> calss = testClassLoader.loadClass("com.notecode.test.bobo1");
Object o = calss.newInstance();
System.out.println("calss对象:" + calss.hashCode());
System.out.println("实例对象:" + o);
System.out.println("类加载器:" + o.getClass().getClassLoader());
}
}
class bobo1{
bobo1(){
System.out.println(bobo1.class.getClassLoader());
//磁盘外的class文件
System.out.println(bobo.class);
}
}