package cn.dongqing.classloader;
import cn.dongqing.demo.entity.LongLong;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Method;
/**
* 自定义类加载器
*
* @date 2020/4/2
*/
public class MyClassLoader extends ClassLoader {
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] data = this.getData(name);
return this.defineClass("cn.dongqing.demo.entity.LongLong", data, 0, data.length);
}
public static void main(String[] args) throws Exception {
LongLong longLong = new LongLong();
Class<? extends LongLong> aClass1 = longLong.getClass();
System.out.println(aClass1.getClassLoader());
MyClassLoader classLoader = new MyClassLoader();
// 不会引起类初始化,不会运行静态代码块,可以看底层调用,resolve=false;
Class<?> aClass = classLoader.findClass("F:\\dairy-queen\\target\\classes\\cn\\dongqing\\demo\\entity" +
"\\LongLong.class");
// 实例化首先要初始化类,所有会运行静态代码块
Object o = aClass.newInstance();
System.out.println(aClass.getClassLoader());
Method doSomething = aClass.getMethod("doSomething", String.class);
doSomething.invoke(o, "测试类加载器");
// 不会引起类初始化,不会运行静态代码块,可以看底层调用,resolve=false;
Class<?> aClass2 = classLoader.findClass("F:\\dairy-queen\\target\\classes\\cn\\dongqing\\demo\\entity" +
"\\LongLong.class");
System.out.println(aClass1 == aClass);
System.out.println(aClass1);
System.out.println(aClass);
System.out.println(aClass2);
System.out.println(aClass == aClass2);
}
private byte[] getData(String name) {
File file = new File(name);
if (file.exists()) {
FileInputStream in = null;
ByteArrayOutputStream out = null;
try {
in = new FileInputStream(file);
out = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int size = 0;
while ((size = in.read(buffer)) != -1) {
out.write(buffer, 0, size);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return out.toByteArray();
} else {
return null;
}
}
}
同一个类,可以被不同类加载器加载,会导致堆中出现两个Class对象,如果类加载器继承了系统的三个类加载器,parent != null,则只会加载一次。
自定义来加载器加载同一个类,多次会抛出异常
Exception in thread "main" java.lang.LinkageError: loader (instance of cn/dongqing/classloader/MyClassLoader): attempted duplicate class definition for name: "cn/dongqing/demo/entity/LongLong"
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
at java.lang.ClassLoader.defineClass(ClassLoader.java:642)
at cn.dongqing.classloader.MyClassLoader.findClass(MyClassLoader.java:22)
at cn.dongqing.classloader.MyClassLoader.main(MyClassLoader.java:39)
自定义类加载器
最新推荐文章于 2023-05-01 14:12:15 发布