java热加载
一晃眼,又是周日了.刚吃完中饭,写篇博客了.今天就说一说昨天看的java热加载,我们都知道java是从.java文件编译后成为.class文件,再加载到虚拟机中进行运行的....现在的问题是,我们怎么判断一个class文件是否更新了呢?我们再进行把这个更新后的class文件加载进去呢?热加载能够节约我们大量的调试时间,避免了因为修改了一个类的一点代码,就全部重启整个项目,像我现在...
一晃眼,又是周日了.刚吃完中饭,写篇博客了.
今天就说一说昨天看的java热加载,我们都知道java是从.java文件编译后成为.class文件,再加载到虚拟机中进行运行的....现在的问题是,我们怎么判断一个class文件是否更新了呢?
我们再进行把这个更新后的class文件加载进去呢?
热加载能够节约我们大量的调试时间,避免了因为修改了一个类的一点代码,就全部重启整个项目,像我现在的项目,启动时间就半分钟,旧的等半分钟,也没有别的办法.有了热部署之后就只需要重新加载需改后的java的class文件了.
下面会用代码讲解怎么进行热加载.
1.首先我们先一个接口,实现此接口的类进行热加载
/**
* Created by zk on 2017/12/23.
* 作用: classload.
* 实现这个接口的子类需要动态更新(热加载)
*/
public interface BaseManager {
void logic();
}
2.写接口的实现类
/**
* Created by zk on 2017/12/23.
* 作用: classload.
* 实现接口,此类需要实现java类的热加载功能
*/
public class MyManager implements BaseManager {
@Override
public void logic() {
System.out.println("zhaojun i miss you very much.... ");
System.out.println("today is 周六了");
}
}
3.对要进行热加载的类的信息进行封装,方便后面进行类的信息的判断
/**
* Created by zk on 2017/12/23.
* 作用: classload.
* 封装要加载类的信息
*/
public class LoadInfo {
//自定义的类加载器
private MyClassLoader myClassLoader;
//记录要加载的类的时间戳 --加载的时间
private long loadTime;
private BaseManager baseManager;
public LoadInfo(MyClassLoader myClassLoader, long loadTime) {
this.myClassLoader = myClassLoader;
this.loadTime = loadTime;
}
public void setBaseManager(BaseManager baseManager) {
this.baseManager = baseManager;
}
public MyClassLoader getMyClassLoader() {
return myClassLoader;
}
public long getLoadTime() {
return loadTime;
}
public BaseManager getBaseManager() {
return baseManager;
}
}
4.封装自己的classLoad,进行class的重新加载到JVM中去
/**
* Created by zk on 2017/12/23.
* 作用: classload.
* 自定义java类加载器,来实现java的类的热加载
*/
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 {
byte[] data=this.loadClassData(name);
//返回加载后的Class对象
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 bos = new ByteArrayOutputStream();
int b = 0;
while ((b = is.read()) != -1) {
bos.write(b);
}
is.close();
return bos.toByteArray();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
5.获取class,对其进行判断,没有加载加重新加载到JVM中去,或者修改了也重新加载
/**
* Created by zk on 2017/12/23.
* 作用: classload.
* 工厂模式,加载manager 的工厂
*/
public class ManagerFactory {
//加载热加载类的加载信息
private static final Map<String,LoadInfo> loadTimeMap=new HashMap<String,LoadInfo>();
//要加载的类的classpath
public static final String CLASS_PATH="C:/workspace/idea/thinkinJava/out/production/thinkinJava/classload";
//实现热加载的类的全名称,包名+类名
public static final String MY_MANAGER="classload.MyManager";
/**
* 获取manager
* @param className
* @return
*/
public static BaseManager getManager(String className){
File loadFile = new File(CLASS_PATH + className.replace(".", "/" + ".class"));
long lastModified=loadFile.lastModified();
//不包含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).getBaseManager();
}
public 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.setBaseManager(manager);
loadTimeMap.put(className,loadInfo);
}
/**
* 以反射的方式创建baseManager子类对象
* @param loadClass
* @return
*/
private static BaseManager newInstance(Class<?> loadClass) {
try {
return (BaseManager) loadClass.getConstructor(new Class[]{}).newInstance(new Object[]{});
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return null;
}
}
6.后台启动一条线程,一直进行监控.与变化就加载进行
/**
* Created by zk on 2017/12/23.
* 作用: classload.
* 后台启动一条线程,刷新重新加载实现了热加载的类
*/
public class MsgHandle implements Runnable {
@Override
public void run() {
while (true){
BaseManager manager = ManagerFactory.getManager(ManagerFactory.MY_MANAGER);
manager.logic();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
7.编写测试类
/**
* Created by zk on 2017/12/23.
* 作用: classload.
* 测试java类的热加载
*
*
* 注意IDEA不是实时编译的,请在eclipse上debug试验
*/
public class ClassLoaderTest {
public static void main(String[] args) {
new Thread(new MsgHandle()).start();
}
}
注意使用IDEA需要进行设置.才能看出来效果.下面是设置的链接.注意修改.
http://blog.csdn.net/u013938484/article/details/77541050
使用eclipse直接进行debug,就可以进行热加载了
Java Framework,欢迎各位前来交流java相关
QQ群:965125360
更多推荐
所有评论(0)