一、常量
interface Constants {
String BASEDIR = "D:\\";
String SUFFIX = ".class";
}
二、重写类加载器到达加载指定目录的类
class MyClassLoader extends ClassLoader {
@Override
protected Class<?> findClass(String name) {
String myPath = new File(Constants.BASEDIR + name + Constants.SUFFIX).toURI().toString();
System.out.println(myPath);
byte[] cLassBytes = null;
Path path = null;
try {
path = Paths.get(new URI(myPath));
cLassBytes = Files.readAllBytes(path);
} catch (IOException | URISyntaxException e) {
e.printStackTrace();
}
Class clazz = defineClass(name, cLassBytes, 0, cLassBytes.length);
return clazz;
}
}
三、Java动态编译
public class TrendsJava {
public static void main(String[] args) {
String code = " System.out.println(\"Hello World!\"+(13+2*5/3));\n" +
" for (int i = 0; i <10; i++) {\n" +
" System.out.println(i);\n" +
" }";
try {
run(code);
} catch (Exception e) {
e.printStackTrace();
}
}
private synchronized static File compile(String code) throws Exception {
File file = File.createTempFile("JavaRuntime", ".java", new File(Constants.BASEDIR));
file.deleteOnExit();
// 获得类名
String classname = getBaseFileName(file);
// 将代码输出到文件
PrintWriter out = new PrintWriter(new FileOutputStream(file));
out.println(getClassCode(code, classname));
out.close();
// 编译生成的java文件
String[] cpargs = new String[]{"-d", Constants.BASEDIR, file.getName()};
System.out.println(System.getProperty("user.dir"));
//动态编译
JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
int status = javac.run(null, null, null, "-d", Constants.BASEDIR, Constants.BASEDIR + file.getName());
if (status != 0) {
throw new Exception("语法错误!");
}
return file;
}
public static synchronized void run(String code) throws Exception {
String classname = getBaseFileName(compile(code));
new File(Constants.BASEDIR + classname + Constants.SUFFIX)
.deleteOnExit();
try {
MyClassLoader loader = new MyClassLoader();
Class cls = loader.findClass(classname);
Method main = cls.getMethod("method", null);
main.invoke(cls, null);
} catch (Exception se) {
se.printStackTrace();
}
}
//将一块代码封装到 method函数中
private static String getClassCode(String code, String className) {
StringBuffer text = new StringBuffer();
text.append("public class " + className + "{\n");
text.append(" public static void method(){\n");
text.append(" " + code + "\n");
text.append(" }\n");
text.append("}");
return text.toString();
}
private static String getBaseFileName(File file) {
String fileName = file.getName();
if (fileName.contains(".")) {
return fileName.split("\\.")[0];
} else {
return fileName;
}
}
}