可编程的编译器

banq 09-12-24

Java通过反射机制可以动态加载一个编译好的类,那么能否直接加载源码类呢?Java 6的javax.tools包提供了在运行时刻,对Java源码编译等功能。可用于:
1. 在文件服务器上生成一个Java文件,然后编译它。
2. 编译Java文件,然后生成一个Jar文件,如果这个Jar文件在classpath中,我们是否可动态加载这个Jar呢?
3. 编写自己的IDE工具。

详细使用见文章:Programmatic Compilation with Java

以下是案例代码:

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;

import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import javax.tools.JavaCompiler.CompilationTask;
import sun.tools.java.ClassFile;

public class CodeCompiler {

public static void main(String[] args) {
try{
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager fileManager = compiler.getStandardFileManager(
null, null, null);
Iterable compilationUnits1 = fileManager
.getJavaFileObjects("D:\\TestClass.java");
CompilationTask task = compiler.getTask(null, fileManager, null, null,
null, compilationUnits1);

// Perform the compilation task.
task.call();
fileManager.close();
ClassFile cf = new ClassFile(new File(
"TestClass.class"));
validateDefaultMethods(cf);

}catch(IOException ioe){
ioe.printStackTrace();
}
}

protected static void validateDefaultMethods(ClassFile clazzInfo) {
boolean hasEquals = false;
boolean hasHashCode = false;
boolean hasToString = false;
for (Method method : clazzInfo.getClass().getMethods()) {
String methodName = method.getName();
Class[] types = method.getParameterTypes();
if (
"equals".equals(methodName) && types.length == 1) {
if (
"java.lang.Object".equals(types[0])) {
hasEquals = true;
}
} else if (
"hashCode".equals(methodName) &&
types.length == 0) {
hasHashCode = true;
}else if(
"toString".equals(methodName)&&
types.length == 0){
hasToString = true;

}
}
if(hasEquals&&hasHashCode&&hasToString){
System.out.println(
"Valid Code");
}else{
System.out.println(
"Invalid Code");
}
}

}

1