通过Runtime调用JAVA,启动新的进程去操作
Runtime runtime = Runtime.getRuntime();
Process process = runtime.exec("javac -cp -D:/MyJava/ HelloWorld.java");
通过JavaCompiler动态的进行编译(6.0以后引入的新功能)
public static int compileFile(String sourceFile){ //模拟JAVA源文件地址 sourceFile = "E:/MyJava/HelloWorld.java"; //获取编译器对象 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); /* 执行编译操作 第一个参数inputStream :为JAVA编译器提供参数 第二个参数outputStream :得到JAVA编译器的输出信息 第三个参数OutputStream :接收编译器的错误信息 第四个参数:可变参数(String[]),能传入一个或者多个JAVA源文件的路径 返回值:0表示成功编译,非0表示编译失败 */ int result = compiler.run(null, System.out, System.out, sourceFile); if(result == 0){ System.out.println("编译成功"); }else{ System.out.println("编译失败"); } return result; }
Runtime runtime = Runtime.getRuntime(); Process process = runtime.exec("java -cp -D:/MyJava/ HelloWorld.java");
public static void run(String dir,String classFile)throws Exception{ //目标目录 dir = "E:/MyJava/"; //目标class文件 classFile = "HelloWorld"; //创建目录url类 URL[] urls = new URL[]{new URL("file:/"+dir)}; //获取url类加载器 URLClassLoader classLoader = new URLClassLoader(urls); //加载指定的class文件 Class clazz = classLoader.loadClass(classFile); //获取其main方法 Method mainMethod = clazz.getMethod("main", String[].class); /* 执行main方法,传递字空符数组参数 因为main方法是static方法,所以可以不用传递对象 # 强制转换的原因 * 可变参数是jdk5之后的东西 * 如果说不把这个String[]转换为Object的话 * String[]里面的每个参数,都会被当作一个新的String[]被main方法加载 * 而main方法的参数只有一个 */ mainMethod.invoke(null, (Object)new String[]{}); }
1,BCEL 2,ASM 3,CGLIB 4,Javassist
1,字节码操作 2,反射
* 在易用性方面: 1. JDK代理是最简单方便的,只需要使用Proxy和InvocationHandler两个类,不过只能代理接口。 2. 其次是CGLIB,也很方便,不过需要引入CGLIB的JAR包。 3. Javassist需要用用字符串拼接Java源代码,稍微会比较繁琐。 4. 最麻烦的是ASM,需要手工写字节码,一般人可能还写不出来。 * 在代理对象的创建速度上 1. JDK代理与ASM都很快,比最慢的CGLIB快20倍以上。 2. 考虑到易用性,在对接口进行动态代理时,使用JDK代理应该是最合适的。 3. 在不能使用JDK代理的情况下,可以考虑使用CGLIB或者Javassist。 4. CGLIB的缺点是创建代理对象的速度慢,Javassist的缺点是需要手动编写Java源码。 5. 如果非要在这个两个中选择一个,那么只有在对性能要求非常高的情况下选择Javassist,其他一般情况下,个人认为CGLIB是比较合适的。