概述
注意:
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动态编译和类的重新加载所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复