可编程的编译器

09-12-24 banq

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");
	        }
	    }

}
<p>

1