即便是同個ClassLoader類的兩個是實例,加載同個類也會不同。因此實現類的熱部署能夠建立不一樣ClassLoader的實例對象,經過這兩個不一樣的實例對象加載同名的類。發現xx.class文件被修改就執行加載。java
package dou_dir_list;this
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;spa
public class ClassReloader extends ClassLoader {
private String classPath;
String classname = "dou_dir_list.ListTest";
public ClassReloader(String classPath){
this.classPath = classPath;
}
protected Class<?> findClass(String name) throws ClassNotFoundException {
byte[] classData = getData(name);
if(classData == null){
throw new ClassNotFoundException();
}else{
return defineClass(classname, classData, 0, classData.length);
}
}
private byte[] getData(String className) {
String path = classPath + className;
try {
InputStream is = new FileInputStream(path);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
byte[] buffer = new byte[2048];
int num = 0;
while((num = is.read(buffer)) != -1){
stream.write(buffer,0,num);
}
return stream.toByteArray();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) {
/**
* 同路徑同名的某xx.class文件由兩個不一樣的ClassLoader實例對象分別加載後再實例出的對象是兩個不一樣的實例
*/
try {
String path = "E:/develop_workspaces/ssm/my_linked_list/bin/dou_dir_list/";
ClassReloader reloader = new ClassReloader(path);
Class r = reloader.findClass("ListTest.class");
System.out.println(r.newInstance());
ClassReloader reloader2 = new ClassReloader(path);
Class r2 = reloader2.findClass("ListTest.class");
System.out.println(r2.newInstance());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
原理是這樣,這種方式能夠爲在開發時修改類頻繁重啓節省些時間。可是原來已經被引用的對象就很差讓JVM去棧中替換了,這違反JVM的設計原則。還有點問題是加載的類會進入PermGen,在Full GC時纔回收,因此改動頻繁時間長了可能會有溢出問題,因此也就開發時用用。JVM不知道運行時類型,只知道編譯類型。能夠像JSP同樣不保存對象狀態,建立使用後當即釋放,再修改又是新的。設計