Java动态编译和类的重新加载

来源:互联网 发布:神州量子网络 招聘 编辑:程序博客网 时间:2024/05/16 07:09
注意:

1.动态编译的class文件不要放到jre的ClassPath中,在jre在ClassPath中找到的类只会加载一次。
2.使用反射获取类的时,如果需要获取最新生成的,需要重新实例化一个类加载器,因为旧的类加载器已经加载过这个类,再次加载只会加载上次那个。而重新实例化的类加载器没有加载过这个类,所以会重新去定义、链接和加载。




Main.java

public class Main {public static void main(String[] args) {String fullClassName = "MyObj";String code = "public class MyObj implements MyInterface{public void sayHello(){System.out.println(666);}}";String code_2 = "public class MyObj implements MyInterface{public void sayHello(){System.out.println(777);}}";String code_3 = "public class MyObj implements MyInterface{public void sayHello(){System.out.println(888);}}";load(code,fullClassName);load(code_2,fullClassName);load(code_3,fullClassName);}private static void load(String code, String fullClassName) {new MyClassCompiler(fullClassName, code).compile();try {MyInterface myObj = (MyInterface) new MyClassLoader().loadClass(fullClassName).newInstance();myObj.sayHello();} catch (InstantiationException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (ClassNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}


MyClassCompiler.java

import java.io.File;import java.io.IOException;import java.net.URI;import java.net.URISyntaxException;import java.util.Arrays;import javax.tools.JavaCompiler;import javax.tools.JavaCompiler.CompilationTask;import javax.tools.JavaFileObject;import javax.tools.JavaFileObject.Kind;import javax.tools.SimpleJavaFileObject;import javax.tools.ToolProvider;public class MyClassCompiler {private String simpleClassName;private String code;private String classPath = System.getProperty("user.dir") + File.separator + "myFolder";public MyClassCompiler(String simpleClassName, String code) {this.simpleClassName = simpleClassName;this.code = code;}public boolean compile() {try {JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();JavaFileObject javaFile = new SimpleJavaFileObject(new URI(simpleClassName + ".java"), Kind.SOURCE) {@Overridepublic CharSequence getCharContent(boolean arg)throws IOException {return code;}};CompilationTask task = compiler.getTask(null, null, null,Arrays.asList("-d", classPath), null,Arrays.asList(javaFile));return task.call();} catch (URISyntaxException e) {e.printStackTrace();return false;}}public String getSimpleClassName() {return simpleClassName;}public void setSimpleClassName(String simpleClassName) {this.simpleClassName = simpleClassName;}public String getCode() {return code;}public void setCode(String code) {this.code = code;}public String getClassPath() {return classPath;}public void setClassPath(String classPath) {this.classPath = classPath;}}


MyClassLoader.java


import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;public class MyClassLoader extends ClassLoader {private boolean alwaysDefineClass = true;private String classPath = System.getProperty("user.dir") + File.separator + "myFolder";@Overrideprotected Class<?> findClass(String fullClassName)throws ClassNotFoundException {Class<?> clazz = null;// clazz = findLoadedClass(fullClassName);// if(alwaysDefineClass || clazz == null){byte[] raw = readClassBytes(fullClassName);clazz = defineClass(fullClassName, raw, 0, raw.length);resolveClass(clazz);// }return clazz;}private byte[] readClassBytes(String fullClassName) {byte[] raw = null;InputStream stream = null;File file = new File(classPath + File.separator+ fullClassName.replaceAll("\\.", "/") + ".class");try {stream = new FileInputStream(file);raw = new byte[(int) file.length()];stream.read(raw);} catch (Exception e) {} finally {try {stream.close();} catch (IOException e) {}}return raw;}public boolean isAlwaysDefineClass() {return alwaysDefineClass;}public void setAlwaysDefineClass(boolean alwaysDefineClass) {this.alwaysDefineClass = alwaysDefineClass;}public String getClassPath() {return classPath;}public void setClassPath(String classPath) {this.classPath = classPath;}}



interface.java


public interface MyInterface { public void sayHello();}




原创粉丝点击