一:动态编译(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(); } } }
Dynamic Compiler
最新推荐文章于 2024-09-12 09:00:00 发布
本文介绍了Java中动态编译的两种主要形式,并详细讲解了如何使用JavaCompiler进行编译及执行,包括通过Runtime和反射机制执行编译后的类。
388

被折叠的 条评论
为什么被折叠?



