`
san_yun
  • 浏览: 2608119 次
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

用ClassLoader实现热部署

 
阅读更多

几天研究了一下Tomcat的ClassLoader,在一年多以前,每改一下Java源码都要启动一下Tomcat,觉得很不爽。后来,

生锅锅教了我一招,其实改Java源码是不用重启Tomcat的(主要是改方法内的代码),这就是所谓的“热部署”。一直对这个

 

比较好奇,这是怎么实现的呢?

 

        下面就来简单的模拟一下热部署,其实原理是比较简单的,就是对比class文件的修改时间,如果class是被修改过了,那么

 

就用ClassLoader把新的class文件重新加载到内存中。

 

ClassLoader的主要代码:
package classloader; 

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.text.MessageFormat;

/**
 * 动态加载class文件
 * @author Ken
 * @since 2013-02-17
 *
 */
public class DynamicClassLoader extends ClassLoader {
	
	// 文件最后修改时间 
	private long lastModified;
	
	// 加载class文件的classpath
	private String classPath;
	
	/**
	 * 检测class文件是否被修改
	 * @param filename
	 * @return
	 */
	private boolean isClassModified(String name) {
		File file = getFile(name);
		if (file.lastModified() > lastModified) {
			return true;
		}
		return false;
	}
	
	public Class<?> loadClass(String classPath, String name) throws ClassNotFoundException {
		this.classPath = classPath;
		if (isClassModified(name)) {
			return findClass(name);
		}
		return null;
	}

	/**
	 * 获取class文件的字节码
	 * @param name		类的全名
	 * @return
	 */
	private byte[] getBytes(String name) {
		byte[] buffer = null;
		FileInputStream in = null;
		try {
			File file = getFile(name);
			lastModified = file.lastModified();
			in = new FileInputStream(file);
			buffer = new byte[in.available()];
			in.read(buffer);
			return buffer;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				in.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return buffer;
	}

	/**
	 * 获取class文件的真实路径
	 * @param name
	 * @return
	 */
	private File getFile(String name) {
		String simpleName = "";
		String packageName = "";
		if (name.indexOf(".") != -1) {
			simpleName = name.substring(name.lastIndexOf(".") + 1);
			packageName = name.substring(0, name.lastIndexOf(".")).replaceAll("[.]", "/");
		} else {
			simpleName = name;
		}
		File file = new File(MessageFormat.format("{0}/{1}/{2}.class", classPath, packageName, simpleName));
		return file;
	}

	@Override
	protected Class<?> findClass(String name) throws ClassNotFoundException {
		byte[] byteCode = getBytes(name);
		return defineClass(null, byteCode, 0, byteCode.length);
	}
}
  被加载的类:
package test.classloader;

public class Hello {

	public String sayHello(String name) {
		return "Hello." + name;
	}
}
 
package classloader; 

import java.lang.reflect.Method;

public class DynamicClassLoaderTest {

	public static void main(String[] args) throws Exception {
		while (true) {
			DynamicClassLoader loader = new DynamicClassLoader();
			Class<?> clazz = loader.loadClass("F:\\JavaProjects\\MyTomcat\\bin", "test.classloader.Hello");
			Method method = clazz.getMethod("sayHello", String.class);
			System.out.println(method.invoke(clazz.newInstance(), "Ken"));
			// 每隔3秒钟重新加载
			Thread.sleep(3000);
		}
	}
}
 
分享到:
评论

相关推荐

    classloader做的一个热部署

    eclipse工程格式 博文链接:https://aga.iteye.com/blog/200818

    classloader 热部署

    博文链接:https://kuangbaoxu.iteye.com/blog/206472

    CustomClassLoader源码

    利用JAVA中的ClassLoader实现热部署

    Java类热替换(热部署)源码

    Java 自定义ClassLoader 实现类的热替换核心代码

    Jdk 动态编译 Java 源码测试 Demo

    Jdk 动态编译 Java 源码测试 Demo 通过 Jdk 工具类,直接将 Java 源码编译为 Class 字节码,并可加载为 Class 对象...通过上面的实现,可以在线动态修改源码,并触发编译,加载到线上项目内,实现类似于热 部署的效果

    springboot参考指南

    热交换 viii. 20. 打包用于生产的应用程序 ix. 21. 接下来阅读什么 5. IV. Spring Boot特性 i. 22. SpringApplication i. 22.1. 自定义Banner ii. 22.2. 自定义SpringApplication iii. 22.3. 流畅的构建API iv. ...

    超级有影响力霸气的Java面试题大全文档

    静态INCLUDE用include伪码实现,定不会检查所含文件的变化,适用于包含静态页面&lt;%@ include file="included.htm" %&gt; 26、什么时候用assert。 assertion(断言)在软件开发中是一种常用的调试方式,很多开发语言中都...

    java 面试题 总结

    静态INCLUDE用include伪码实现,定不会检查所含文件的变化,适用于包含静态页面&lt;%@ include file="included.htm" %&gt; 23、什么时候用assert。 assertion(断言)在软件开发中是一种常用的调试方式,很多开发语言中都...

    JAVA核心知识点整理(有效)

    1. 目录 1. 2. 目录 .........................................................................................................................................................1 JVM ........................

Global site tag (gtag.js) - Google Analytics