首页 > 代码库 > Java动态编译

Java动态编译

   Java从jdk6.0开始引入了动态编译机制  

 动态编译引用场景:

          - 可以做一个浏览器端编写java代码,上传服务器和运行的在线评测系统 

          - 服务器动态加载某些类文件进行编译

 动态编译做法:

          - 通过 Runtime调用javac 启动新的进程去操作 

          - 通过JavaCompiler进行动态编译

          --通过反射编运行编译好的类

示例 1 通过Runtime调用javac 启动新的进程去操作     

package compiler;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;

public class RuntimeTest {
	public static void main(String[] args) throws IOException {
		Runtime run = Runtime.getRuntime(); // 获取runtime对象
		Process process = run.exec("java -cp e:/szw/myjava");// 编译
		InputStream in = process.getInputStream(); // 根据process后去输入流,用于打印输出到控制台
		BufferedReader reader = new BufferedReader(new InputStreamReader(in));
		String info = "";
		while ((info = reader.readLine()) != null) {
			System.out.println(info);

		}
	}
}

  示例二 通过JavaCompiler进行动态编译 

package compiler;

import javax.tools.JavaCompiler;
import javax.tools.Tool;
import javax.tools.ToolProvider;

public class CompilerTest {
	public static void main(String[] args) {
		JavaCompiler jc = ToolProvider.getSystemJavaCompiler();
		int flg = jc.run(null, null, null, "e:/szw/myjava.java");// 返回int 如果是0编译成功其他编译失败
		// 第一个参数:为java编译器提供参数
		// 第二个参数:得到java编译器的输出信息
		// 第三个参数:接受编译器的错误信息
		// 第四个参数:可变参数(是一个String数组)能传入一个或多个java源文件
		// 返回值:0表示编译成功,非0表示编译失败
		System.out.println(flg == 0 ? "编译成功" : "编译失败");
	}
}

  --通过反射编运行编译好的类

   

package compiler;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;

public class UrlClassL {
	public static void main(String[] args) throws MalformedURLException, ClassNotFoundException, NoSuchMethodException,
			SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {

		URL[] url = new URL[] { new URL("file:/" + "e:/szw/") };
		URLClassLoader loader = new URLClassLoader(url);
		// 调用类加载的main方法
		Class c = loader.loadClass("myjava");
		Method method = c.getMethod("main", String[].class);
		method.invoke(null, (Object) new String[] { "b", "c" });// 因为main方法是静态方法,不需要对象,所以可以为空
		// 传参时,将String数组转为 object ,如果不转,编译器会把 它变成这样的一个调用 invoke(null,"b","c")
		// 以多个参数的形式传入,会报错,因此必须要加上

	}
}

  

               

Java动态编译