所以一个class被一个ClassLoader实例加载过的话,就不能再被这个ClassLoader实例再次加载(这里的加载指的是,调用了defileClass(...)放方法,重新加载字节码、解析、验证。)。而系统默认的AppClassLoader加载器,他们内部会缓存加载过的class,重新加载的话,就直接取缓存。所与对于热加载的话,只能重新创建一个ClassLoader,然后再去加载已经被加载过的class文件。
下面看一个class热加载的例子:
代码:HotSwapURLClassLoader自定义classloader,实现热替换的关键
1 package testjvm.testclassloader;
2
3 import java.io.File;
4 import java.io.FileNotFoundException;
5 import java.net.MalformedURLException;
6 import java.net.URL;
7 import java.net.URLClassLoader;
8 import java.util.HashMap;
9 import java.util.Map;
10
11 /**12 * 只要功能是重新加载更改过的.class文件,达到热替换的作用13 *@authorbanana14 */
15 public class HotSwapURLClassLoader extends URLClassLoader {
16 //缓存加载class文件的最后最新修改时间17 public static Map cacheLastModifyTimeMap = new HashMap();
18 //工程class类所在的路径19 public static String projectClassPath = "D:/Ecpworkspace/ZJob-Note/bin/";
20 //所有的测试的类都在同一个包下21 public static String packagePath = "testjvm/testclassloader/";
22
23 private static HotSwapURLClassLoader hcl = new HotSwapURLClassLoader();
24
25 public HotSwapURLClassLoader() {
26 //设置ClassLoader加载的路径27 super(getMyURLs());
28 }
29
30 public static HotSwapURLClassLoader getClassLoader(){
31 return hcl;
32 }
33
34 private static URL[] getMyURLs(){
35 URL url = null;
36 try {
37 url = new File(projectClassPath).toURI().toURL();
38 } catch (MalformedURLException e) {
39 e.printStackTrace();
40 }
41 return new URL[] { url };
42 }
43
44 /**45 * 重写loadClass,不采用双亲委托机制("java."开头的类还是会由系统默认ClassLoader加载)46 */
47 @Override
48 public Class> loadClass(String name,boolean resolve) throws ClassNotFoundException {
49 Class clazz = null;
50 //查看HotSwapURLClassLoader实例缓存下,是否已经加载过class51 //不同的HotSwapURLClassLoader实例是不共享缓存的52 clazz = findLoadedClass(name);
53 if (clazz != null ) {
54 if (resolve){
55 resolveClass(clazz);
56 }
57 //如果class类被修改过,则重新加载58 if (isModify(name)) {
59 hcl = new HotSwapURLClassLoader();
60 clazz = customLoad(name, hcl);
61 }
62 return (clazz);
63 }
64
65 //如果类的包名为"java."开始,则有系统默认加载器AppClassLoader加载66 if(name.startsWith("java.")){
67 try {
68 //得到系统默认的加载cl,即AppClassLoader69 ClassLoader system = ClassLoader.getSystemClassLoader();
70 clazz = system.loadClass(name);
71 if (clazz != null) {
72 if (resolve)
73 resolveClass(clazz);
74 return (clazz);
75 }
76 } catch (ClassNotFoundException e) {
77 //Ignore78 }
79 }
80
81 return customLoad(name,this);
82 }
83
84 public Class load(String name) throws Exception{
85 return loadClass(name);
86 }
87
88 /**89 * 自定义加载90 *@paramname91 *@paramcl92 *@return93 *@throwsClassNotFoundExc