Ai
1 Star 0 Fork 0

syuchen/LearnJVM

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
HotCLassLoaderTest.java 4.72 KB
一键复制 编辑 原始数据 按行查看 历史
宋宇辰 提交于 2022-11-23 20:09 +08:00 . commit
package com.classLoader;
import com.hotClass.Singleton;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
/**
* 自定义加载器实现类的热部署 简单案例
*/
public class HotCLassLoaderTest {
public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
// HotClassLoader hotClassLoader = new HotClassLoader();
// Class testClass = hotClassLoader.loadClass("com.hotClass.Singleton");
//由于HotCLassLoaderTest类是由AppCLassLoader加载的,因此只要这里显式引用到了Singleton类,并且AppCLassLoader可以加载到它,那么A就会加载,
// 这就与HotClassLoader加载的类对象冲突了,H加载的类的实例对象不能强转为A加载的类的实例对象,故下面这样写会报错
// Object test = testClass.newInstance();
// Singleton singleton = (Singleton) aClass.getMethod("getInstance").invoke(test);
Singleton.HotClassMonitor.startMonitoring();
new Thread(() -> {
while (true) {
try {
//热加载之后,这里实际上是A加载器加载的类对象里存储的H加载器加载的类对象的实例对象singleObject
Object singleObject = Singleton.getInstance();
System.out.println(singleObject.getClass().getClassLoader());
singleObject.getClass().getMethod("testPrint").invoke(singleObject);
} catch (IllegalAccessException | InstantiationException | ClassNotFoundException | NoSuchMethodException | InvocationTargetException e) {
e.printStackTrace();
}
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
/**
* jvm规定相同类对象(1.类全名相同,2.加载它的加载器实例对象相同)不能重复加载
* 故热加载时需要new一个新的HotClassLoader实例,不能使用单例
*/
public static class HotClassLoader extends ClassLoader{
public final static String classFilePath = "D:\\DownLoadProject\\LearnJVM\\out\\production\\LearnJVM\\"; //编译后classpath路径
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
return loadClass(name, false);
}
/**
* 重写loadClass方法,拦截指定类 不委托给父类加载器处理
*/
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException{
//注意:loadClass也会加载name类中引用到的相关的类,例如其父类Object,而Object类需要委托加载,故这里要加个判断
if (name.startsWith("com.hotClass")) {
synchronized (getClassLoadingLock(name)) {
//findLoadedClass:若存在name相同并且加载器实例对象相同的类对象 则将其返回,否则返回null
Class<?> c = findLoadedClass(name);
if (c == null) {
c = findClass(name);
}
if (resolve) {
resolveClass(c);
}
return c;
}
}
return super.loadClass(name, resolve);
}
@Override
protected Class<?> findClass(String classCompleteName) throws ClassNotFoundException {
System.out.println("HotClassLoader尝试加载"+classCompleteName);
byte[] result = getClassFromCustomPath(classFilePath +classCompleteName.replace(".", File.separator)+".class");
if (result == null) {
throw new ClassNotFoundException(classCompleteName);
} else {
return defineClass(classCompleteName, result, 0, result.length);
}
}
private byte[] getClassFromCustomPath(String classFilePath) {
File f = new File(classFilePath);
InputStream is = null;
try {
//读取编译后的文件
is = new FileInputStream(f);
byte[] bytes=new byte[is.available()];
is.read(bytes);
return bytes;
} catch (Exception e){
} finally {
try {
if (is != null) {
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
}
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/syuchen/LearnJVM.git
git@gitee.com:syuchen/LearnJVM.git
syuchen
LearnJVM
LearnJVM
master

搜索帮助