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

用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

    美团IDEA插件实现Java应用的热部署实践

    热部署插件的实现原理主要是通过Agent字节码增强、Javassist、Classloader等技术来实现的。Agent字节码增强是指在Java字节码中插入一些用于热部署的代码,以便在运行时可以实现热部署。Javassist是一个Java库,提供...

    支持Java热部署的插件

    Java热部署主要涉及到JVM(Java虚拟机)和类加载器(ClassLoader)的工作机制。JVM在运行时会加载类文件到内存中,当类被修改后,热部署插件能够检测到这种变化,并替换内存中的旧版本类,而不需要停止服务。这个...

    Java基于自定义类加载器实现热部署过程解析

    为了实现热部署,需要使用自定义的ClassLoader替换系统的加载器,创建一个新的ClassLoader,再用它加载Class,得到的Class对象就是新的(因为不是同一个类加载器),再用该Class对象创建一个实例,从而实现动态更新...

    JAVA类加载器分析--热部署的缺陷(有代码示例,及分析)

    解决这些问题的方法包括使用特殊的热部署插件,如JRebel,它通过改变类加载机制来实现实时代码更新,并处理好类的缓存和静态变量问题。另外,开发者还可以通过调整类加载策略,比如使用自定义类加载器,来避免类冲突...

    深入探索 Java 热部署

    要实现热部署,关键在于自定义类加载器(ClassLoader)。通常,JVM 使用双亲委派模型加载类,即从顶层的 Bootstrap ClassLoader 开始,逐级向下查找直至找到合适的类加载器。自定义 ClassLoader 需要监控特定类的...

    关于java热部署知识.doc

    对于EJB,一些服务器允许开发者通过自定义ClassLoader或使用特定的部署配置实现热部署。 此外,还有一些第三方工具和框架,如JRebel、DCEVM(Dynamic Code Evolution VM)、Spring Boot DevTools等,它们提供了更...

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

    当检测到类文件更新时,ClassLoader加载新的字节码,从而实现类的热替换。这是描述中提到的核心方法。 现在,让我们深入到源码层面。自定义ClassLoader通常包括以下步骤: 1. **继承自ClassLoader**:创建一个新的...

    STS热部署方法(springboot).docx

    综上所述,通过引入Spring Boot DevTools并配置相应的属性,开发者可以在STS中实现Spring Boot项目的热部署,从而提高开发效率。在了解了DevTools的工作原理后,开发者可以更好地利用这一工具,避免频繁的手动重启...

    springMVC样例、jreloader实现tomcat热部署

    接着,我们要介绍jreloader如何实现Tomcat的热部署。jreloader通过监听文件系统,一旦发现被监控的类文件发生变化,就会触发类的重新加载。它的工作原理是在Tomcat的生命周期中插入一个监听器,当检测到应用中的类...

    Tomcat 热部署的实现原理详解

    首先,对于Java的类加载器(Classloader),其设计遵循“双亲委派模型”,但当涉及到热部署时,Tomcat使用了一种特殊的方式。在Tomcat中,每个Web应用都有自己的类加载器(WebappClassLoader),这个类加载器负责...

    ClassLoader的 一些测试

    自定义ClassLoader是一种常见的需求,例如在插件系统、热部署等场景。自定义加载器通常需要重写`loadClass(String className)`方法,通过URL读取类的字节流并转换为Class对象。在这个过程中,我们需要注意类的缓存,...

Global site tag (gtag.js) - Google Analytics