Java:ClassLoader实现热加载原理的解析
Posted 你是小KS
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java:ClassLoader实现热加载原理的解析相关的知识,希望对你有一定的参考价值。
1. 声明
当前内容主要为学习和测试实现热加载class的原理:一般class被装载到jvm中的时候此时会触发static的静态代码块执行操作
基本步骤:
- 手动创建ClassLoader来加载特定位置上的class文件
- 更换new新的ClassLoader来再次测试
2. 基本demo
1.创建需要装载的类
public class NoModifyClass {
private String name = "NoModifyClass";
static {
System.out.println("hello");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "NoModifyClass [name=" + name + "]";
}
}
2.开始编写代码进行测试
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
*
* @author hy
* @createTime 2021-07-18 09:39:47
* @description 当前内容主要为使用热加载器方式加载修改后的class文件
*
*/
public class HotLoadTest {
public static void main(String[] args)
throws InstantiationException, IllegalAccessException, ClassNotFoundException {
ClassLoader classLoader = HotLoadTest.class.getClassLoader();
Class<?> loadClass = classLoader.loadClass(NoModifyClass.class.getName());
Object newInstance = loadClass.newInstance();
System.out.println(newInstance);
Class<?> loadClass2 = classLoader.loadClass(NoModifyClass.class.getName());
Object newInstance2 = loadClass2.newInstance();
System.out.println(newInstance2);
MyClassLoader myClassLoader = new MyClassLoader();
Class<?> loadClass3 = myClassLoader.loadClass(NoModifyClass.class.getName());
Object newInstance3 = loadClass3.newInstance();
System.out.println(newInstance3 instanceof NoModifyClass);
//
MyClassLoader2 myClassLoader2 = new MyClassLoader2();
Class<?> loadClass4 = myClassLoader2.loadClass(NoModifyClass.class.getName());
Object newInstance4 = loadClass4.newInstance();
System.out.println("newInstance4 instanceof NoModifyClass=" + (newInstance4 instanceof NoModifyClass));
Class<?> loadClass41 = myClassLoader2.loadClass(NoModifyClass.class.getName());
Object newInstance41 = loadClass41.newInstance();
System.out.println("newInstance41 instanceof NoModifyClass=" + (newInstance41 instanceof NoModifyClass));
// 再次创建一个类加载器,那么加载的类和之前的也不一样
MyClassLoader2 myClassLoader3 = new MyClassLoader2();
Class<?> loadClass31 = myClassLoader3.loadClass(NoModifyClass.class.getName());
Object newInstance31 = loadClass31.newInstance();
System.out.println("newInstance31 instanceof NoModifyClass=" + (newInstance31 instanceof NoModifyClass));
}
static class MyClassLoader extends ClassLoader {
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
// TODO Auto-generated method stub
return super.loadClass(name, resolve);
}
}
static class MyClassLoader2 extends ClassLoader {
@Override
public Class<?> loadClass(String name) throws ClassNotFoundException {
synchronized (getClassLoadingLock(name)) {
Class<?> loadedClass = findLoadedClass(name);
// System.out.println("loadedClass=" + loadedClass);
if (loadedClass == null) {
String fileName = name.substring(name.lastIndexOf(".") + 1);
InputStream is = null;
try {
fileName = "D:/eclipse-workspace/Java8BasicReStudy/target/classes/com/hy/java/hotload/"
+ fileName + ".class";
is = new FileInputStream(new File(fileName));
} catch (Exception e) {
}
if (is == null) {
// System.out.println("找不到文件:" + fileName);
return super.loadClass(name);
}
try {
int available = is.available();
byte[] bytes = new byte[available];
is.read(bytes);
return defineClass(bytes, 0, bytes.length);
} catch (IOException e) {
throw new ClassNotFoundException();
}
}
return loadedClass;
}
}
}
}
测试结果为:
只要打印了hello的就表示该类被装载到了jvm中,说明了
- 相同的ClassLoader的实例中只能有一份class的定义,如果强制再次加载class文件就会得到
Exception in thread "main" java.lang.LinkageError: loader (instance of com/hy/java/hotload/HotLoadTest$MyClassLoader2): attempted duplicate class definition for name: "com/hy/java/hotload/NoModifyClass"
这个异常(通过取消findLoadedClass这个可得到异常信息) - 不同的ClassLoader的实例可以加载相同的class定义,
这就是热加载class的来源(通过丢弃原来的ClassLoader,new新的ClassLoader就可以了)
- 不同的ClassLoader中加载的class最后new出来的实例也是不一样的,无法通过instanceof来判断类型匹配
以上是关于Java:ClassLoader实现热加载原理的解析的主要内容,如果未能解决你的问题,请参考以下文章
从Java的类加载机制谈起:聊聊Java中如何实现热部署(热加载)