Java动态编译和类的重新加载
2013-07-10 17:38
417 查看
注意:
1.动态编译的class文件不要放到jre的ClassPath中,在jre在ClassPath中找到的类只会加载一次。
![](http://img.blog.csdn.net/20130710173541687?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbWVueHVfd29yaw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
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 block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.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) { @Override public 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"; @Override protected 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(); }
相关文章推荐
- 动态生成java、动态编译、动态加载
- Java的动态编译、动态加载、字节码操作
- 动态编译 Java 文件 与 动态加载 Java 类
- eclipse下java动态编译时com.sun.tools.javac.Main类加载问题的解决
- Java类动态加载(一)——java源文件动态编译为class文件
- 动态编译 Java 文件 与 动态加载 Java 类
- JAVA下进行动态编译加载的实例
- 编译时向内核添加新设备 模块的方式动态的将驱动加入内核,但这种方式加入的驱动程序,当系统重新启动时, 还需要重新用模块的方式进行插入,如果是系统内常用的设备驱动采用这种方式进行加载, 就会很不方便。
- java动态编译动态加载方法
- 从String中动态(内存中)编译和加载java类
- 整理一下Java动态编译Java代码,并在加载到内存中然后执行类中方法的api的介绍
- java 动态编译.java文件,然后动态加载运行
- 使用javassist运行时动态重新加载java类及其他替换选择
- JAVA1.6实现动态编译加载运行
- Java_动态重新加载Class总结
- 通过源码包php-5.4.9.tar.gz编译安装PHP之后,如何加载动态模块,不需要重新配置PHP
- Java_动态重新加载Class机制
- 动态生成java、动态编译、动态加载
- Java动态编译源代码并加载执行
- java编程进行动态编译加载代码分享