您的位置:首页 > 编程语言 > Java开发

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

2013-07-10 17:38 417 查看
注意:

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();
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: