java类的热替换

1.背景

一些关键应用不能轻易停止服务,可以尝试在线升级,即在不停止正在运行的系统的情况下进行类(对象)的升级替换。

Java 的 ClassLoader 正是实现这项技术的基础。

2.思想


3.相关类


4.示例

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashSet;
import java.util.Timer;
import java.util.TimerTask;

/*
实验步骤:
1.在项目下增加一个classDirectory目录,里面盛放SayHi.class。
2.运行main方法。
3.替换SayHi.class。观察控制台输出的变化即可。
*/
class HotSwapClassLoader extends ClassLoader {

	// 需要该类加载器直接加载的类文件的基目录
	private String basedir;
	// 需要由该类加载器直接加载的类名
	private HashSet dynamicClassNameSet;

	public HotSwapClassLoader(String basedir, String[] classNames)
			throws FileNotFoundException, IOException {
		super(null); // 指定父类加载器为 null
		this.basedir = basedir;
		dynamicClassNameSet = new HashSet<>();
		loadClassByMe(classNames);
	}

	private void loadClassByMe(String[] classNames)
			throws FileNotFoundException, IOException {
		for (int i = 0; i < classNames.length; i++) {
			loadDirectly(classNames[i]);
			dynamicClassNameSet.add(classNames[i]);
		}
	}

	private Class loadDirectly(String name) throws FileNotFoundException,
			IOException {
		Class cls = null;
		StringBuffer sb = new StringBuffer(basedir);
		String classname = name.replace('.', File.separatorChar) + ".class";
		sb.append(File.separator + classname);
		File classF = new File(sb.toString());
		cls = instantiateClass(name, new FileInputStream(classF),
				classF.length());
		return cls;
	}

	private Class instantiateClass(String name, InputStream fin, long len)
			throws IOException {
		byte[] raw = new byte[(int) len];
		fin.read(raw);
		fin.close();
		return defineClass(name, raw, 0, raw.length);
	}

	protected Class loadClass(String name, boolean resolve)
			throws ClassNotFoundException {
		Class cls = null;
		cls = findLoadedClass(name);
		if (!this.dynamicClassNameSet.contains(name) && cls == null)
			cls = getSystemClassLoader().loadClass(name);
		if (cls == null)
			throw new ClassNotFoundException(name);
		if (resolve)
			resolveClass(cls);
		return cls;
	}

	public static void main(String[] args) throws FileNotFoundException, IOException {
		new Timer().schedule(new TimerTask() {
			
			@Override
			public void run(){ 
			    try { 
			        // 每次都创建出一个新的类加载器
			    	HotSwapClassLoader hotSwapClassLoader = new HotSwapClassLoader("classDirectory/", new String[]{"SayHi"}); 
			        Class cls = hotSwapClassLoader.loadClass("SayHi"); 
			        Object foo = cls.newInstance(); 
			        if(foo instanceof ISayHi)
			        	((ISayHi) foo).sayHi();
			    }  catch(Exception ex) { 
			        ex.printStackTrace(); 
			    } 
			}
		}, 0, 1000L);
	}
}

/*
 public interface ISayHi{
	void sayHi();
}
 */

/*
public class SayHi implements ISayHi {
	@Override
	public void sayHi() {
		System.out.println("hi\tv1");//"hi\tv2"
	}
}
 */

/*
hi	v1
hi	v2
*/


你可能感兴趣的:(java-语法)