java热部署
问题:jvm运行过程中怎么加载生成的java类
public class CompilerMain {
public static void main(String[] args) throws Exception {
testCompiler();
}
public static void testCompiler() throws Exception {
String currentDir = System.getProperty("user.dir");
String src = "public class TestCompiler {"
+ " public void disply() {"
+ " System.out.println(\"Hello\");"
+ "}}";
String filename = currentDir + "/src/TestCompiler.java";
File file = new File(filename);
FileWriter fw = new FileWriter(file);
fw.write(src);
fw.flush();
fw.close();
JavaCompiler jc = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = jc.getStandardFileManager(null, null, null);
Iterable<? extends JavaFileObject> fileObjects = fileManager.getJavaFileObjects(filename);
CompilationTask cTask = jc.getTask(null, fileManager, null, null, null, fileObjects);
cTask.call();
fileManager.close();
URL[] urls = new URL[] { new URL("file:/" + currentDir + "/src/") };
URLClassLoader cLoader = new URLClassLoader(urls);
Class<?> c = cLoader.loadClass("TestCompiler");
cLoader.close();
Object obj = c.newInstance();
Method method = c.getMethod("disply");
method.invoke(obj);
}
}
问题:jvm在运行过程中怎么重写加载一个已经进入内存的类?
package 自定义类加载器;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.*;
import java.lang.reflect.Method;
public class MyClassLoader extends ClassLoader{
private String directory;
public MyClassLoader(String directory){
this.directory=directory;
}
public MyClassLoader(String directory,ClassLoader parent){
super(parent);
this.directory=directory;
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
String file=directory+ File.separator+name.replace(".",File.separator)+".class";
try {
InputStream fileInputStream = new FileInputStream(file);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
byte []buf=new byte[1024];
int len=-1;
while ((len=fileInputStream.read(buf))!=-1){
byteArrayOutputStream.write(buf,0,len);
}
byte []data=byteArrayOutputStream.toByteArray();
fileInputStream.close();
byteArrayOutputStream.close();
return defineClass(name,data,0,data.length);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, IOException {
MyClassLoader myClassLoader = new MyClassLoader("D:\\Idea\\data\\ClassLoders\\out\\production\\ClassLoders");
Class<?> aClass = myClassLoader.findClass("自定义类加载器.Test2");
aClass.newInstance();
FileWriter fileWriter = new FileWriter("./src/自定义类加载器/Test2.java");
fileWriter.write("package 自定义类加载器;\n" +
"public class Test2 {\n" +
" public Test2() {\n" +
" System.out.println(\"2\");\n" +
" }\n" +
"}");
fileWriter.close();
String filename="./src/自定义类加载器/Test2.java";
JavaCompiler jc = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = jc.getStandardFileManager(null, null, null);
Iterable<? extends JavaFileObject> fileObjects = fileManager.getJavaFileObjects(filename);
JavaCompiler.CompilationTask cTask = jc.getTask(null, fileManager, null, null, null, fileObjects);
cTask.call();
fileManager.close();
MyClassLoader myClassLoader1 = new MyClassLoader("D:\\Idea\\data\\ClassLoders\\src",myClassLoader);
Class<?> aClass1 = myClassLoader1.findClass("自定义类加载器.Test2");
aClass1.newInstance();
}
}
这是加载前Test2类
package 自定义类加载器;
public class Test2 {
public Test2() {
System.out.println("3");
}
}
这是修改后,并且进入内存的Test2类
package 自定义类加载器;
public class Test2 {
public Test2() {
System.out.println("2");
}
}