自定义Java类加载器来实现Java类的热加载
public class MyClassLoader extends ClassLoader
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
/**
* 自定义Java类加载器来实现Java类的热加载
* @author liuyazhuang
*
*/
public class MyClassLoader extends ClassLoader {
//要加载的Java类的classpath路径
private String classpath;
public MyClassLoader(String classpath){
super(ClassLoader.getSystemClassLoader());//调用父类的构造方法
this.classpath = classpath;
}
//要复写的核心方法
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
//下面自定义方法加载class文件中的内容
byte[] data = this.loadClassData(name);
//类名,字节数组 ,开始 ,长度
return this.defineClass(name, data, 0, data.length);
}
/**
* 加载class文件中的内容
* @param name
* @return
*/
private byte[] loadClassData(String name) {
try {
name = name.replace(".", "//");//将 "." 变成 "//"
FileInputStream is = new FileInputStream(new File(classpath + name + ".class"));//文件路径
ByteArrayOutputStream baos = new ByteArrayOutputStream();//字节数组输出流
int b = 0;
while ((b = is.read()) != -1) {
baos.write(b);
}
is.close();
return baos.toByteArray();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
实现这个接口的子类需要动态更新
/**
* 实现这个接口的子类需要动态更新
* @author liuyazhuang
*
*/
public interface BaseManager {
public void logic();
}
BaseManager的子类,此类需要实现java类的热加载功能
public class MyManager implements BaseManager {
@Override
public void logic() {
System.out.println("我在慕课网学习呢,我在慕课网上学习了Spring Boot热部署这门课程");
System.out.println("慕课网学习资源很丰富,师资很强大,学习的人很多");
}
}
封装加载类的信息
/**
* 封装加载类的信息
* @author liuyazhuang
*
*/
public class LoadInfo {
//自定义的类加载
private MyClassLoader myLoader;
//记录要加载的类的时间戳-->加载的时间
private long loadTime;
private BaseManager manager;
public LoadInfo(MyClassLoader myLoader, long loadTime) {
super();
this.myLoader = myLoader;
this.loadTime = loadTime;
}
public MyClassLoader getMyLoader() {
return myLoader;
}
public void setMyLoader(MyClassLoader myLoader) {
this.myLoader = myLoader;
}
public long getLoadTime() {
return loadTime;
}
public void setLoadTime(long loadTime) {
this.loadTime = loadTime;
}
public BaseManager getManager() {
return manager;
}
public void setManager(BaseManager manager) {
this.manager = manager;
}
}
加载manager的工厂
/**
* 加载manager的工厂
* @author liuyazhuang
*
*/
public class ManagerFactory {
//记录热加载类的加载信息
private static final Map<String, LoadInfo> loadTimeMap = new HashMap<String, LoadInfo>();
//要加载的类的classpath
public static final String CLASS_PATH = "D:/Workspaces/muke/classloader/bin/";
//实现热加载的类的全名称(包名+类名)
public static final String MY_MANAGER = "com.imooc.classloader.MyManager";
public static BaseManager getManager(String className){
File loadFile = new File(CLASS_PATH + className.replaceAll("\\.", "/") + ".class");
long lastModified = loadFile.lastModified();
//loadTimeMap不包含className为key的LoadInfo信息。证明这个类没有被加载,那么需要加载这个类到JVM
if(loadTimeMap.get(className) == null){
load(className, lastModified);
}//加载类的时间戳变化了,我们同样要重新加载这个类到JVM
else if(loadTimeMap.get(className).getLoadTime() != lastModified){
load(className, lastModified);
}
return loadTimeMap.get(className).getManager();
}
private static void load(String className, long lastModified) {
MyClassLoader myClassLoader = new MyClassLoader(CLASS_PATH);
Class<?> loadClass = null;
try {
loadClass = myClassLoader.loadClass(className);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
BaseManager manager = newInstance(loadClass);
LoadInfo loadInfo = new LoadInfo(myClassLoader, lastModified);
loadInfo.setManager(manager);
loadTimeMap.put(className, loadInfo);
}
//以反射的方式创建BaseManager子类对象
private static BaseManager newInstance(Class<?> loadClass) {
try {
return (BaseManager)loadClass.getConstructor(new Class[]{}).newInstance(new Object[]{});
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException 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();
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
后台启动一条线程不断刷新重新加载实现了热加载的类
public class MsgHandler implements Runnable {
@Override
public void run() {
while (true) {
BaseManager manager = ManagerFactory.getManager(ManagerFactory.MY_MANAGER);
manager.logic();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
测试Java类的热加载
/**
- 测试Java类的热加载
- @author liuyazhuang
*/
public class ClassLoaderTest {
public static void main(String[] args) {
new Thread(new MsgHandler()).start();
}
}