Dynamic Compiler

本文介绍了Java中动态编译的两种主要形式,并详细讲解了如何使用JavaCompiler进行编译及执行,包括通过Runtime和反射机制执行编译后的类。
一:动态编译(Dynamic Compiler)的两种形式
	1、通过Runtime调用javac,启动新的进程
	2、通过JavaCompiler动态编译(重点)


二:操作
  1、获得编译器:
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
  		run()
  2、将字符串通过IO流写入java文件,再进行上面的动态编译
  3、动态执行.class文件:
  		1)Runtime.getRuntime()
  		   exec()(返回类型为Process类)
		   想要查看输出结果还需要进行流操作
 		2)通过反射来执行:这里要注意一下,加载main方法时要强制转型为(Object)
			URL[]
			URLClassLoader
			loadClass()

package com.chen.Base_Points;

import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;

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

/**
 * 认识JavaCompiler
 * 1、获得编译器:
 * 		ToolProvider.getSystemJavaCompiler();
 * 		run()
 * 2、将字符串通过IO流写入java文件,再进行上面的动态编译
 * 3、动态执行.class文件:
 * 		1)Runtime.getRuntime()
 * 		  exec()(返回类型为Process类)
 * 	                  想要查看输出结果还需要进行流操作
 * 		2)通过反射来执行:这里要注意一下,加载main方法时要强制转型为(Object)
 * 		  URL[]
 * 		  URLClassLoader
 * 		  loadClass()
 * @author Administrator
 *
 */
public class Demo01 {

	public static void main(String[] args) {
		// 1、获得编译器
		JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
		// 利用编译器编译文件,编译成功就返回0,否者为非0
		int result = compiler.run(null, null, null, "F:/New/Name.java", "F:/New/Hi.java", "F:/New/First.java");
		System.out.println((result==0)?"编译成功":"编译失败");
		
		// 2、将字符串通过IO流写入java文件,再进行上面的动态编译
		String str = "public class Hi{public static void main(String[] args){System.out.println(\"你好\");}}";
		byte[] data = str.getBytes();
		try {
			OutputStream os = new FileOutputStream("F:/New/Hi.java");// 注意存取文件时的名称
				os.write(data);
				os.flush();
		} catch (Exception e) {
			
			e.printStackTrace();
		}
		
		
		// 3、动态运行文件
		
		// 第一种方式:通过Runtime
		Runtime  run = Runtime.getRuntime();
		try {
			// 注意:要是源文件中有  package com.chen.Base_Points;这类语句时,就无法执行了,因为他要加载类、打包等操作,可能找不到路径
			Process process = run.exec("java -cp  F:/New  Hi");// -cp表示寻找路径  F:/New/表示dir  Hi表示class文件名(可以不加点缀)
			// 在控制台查看输出结果
			InputStream in = process.getInputStream();
			BufferedReader br = new BufferedReader(new InputStreamReader(in));
			String context = null;
			while((context = br.readLine()) != null) {
				
				System.out.println(context);
			}
		} catch (IOException e) {
			
			e.printStackTrace();
		}
		
	
		// 第二种方式:通过反射
		try {
			// 获得文件目录的路径
			URL[] urls = new URL[] {new URL("file:/"+"F:/New/"), new URL("file:/"+"F:/New/")};// ("file:/"+dir)
			// 加载路径
			URLClassLoader loader = new URLClassLoader(urls);
			// 加载类
			Class clazz = loader.loadClass("Hi");
			Class clazz2 = loader.loadClass("Name");
			// 调用加载类的主方法
			Method m = clazz.getDeclaredMethod("main", String[].class);
			m.invoke(null, (Object)new String[] {});
			Method m2 = clazz2.getDeclaredMethod("main", String[].class);
			m2.invoke(null, (Object)new String[] {});
			// 这里要注意一下,强转型为(Object),因为可变参数是JDK5.0以后才有的,如果不加转型的话
			// 当main()方法传递参数时容易发生参数不匹配的问题。
			// 如m.invoke(null, (Object)new String[] {"aa", "bb"});会被编译成
			// m.invoke(null, "aa", "bb")这就发生了参数不匹配的问题

		} catch (Exception e) {
			
			e.printStackTrace();
		}
		
	}
}


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值