Java动态编译详解
Java的动态编译知识,真真在实际开发中并不是经常遇到。但是学习java动态编译
有助于我们从更深一层次去了解java。对掌握jdk的动态代理模式,还有比如CGLIB,Spring的AOP 的原理就很有帮助。这样我们在学习其他一些开源框架的时候就能够知其然也知其所以然。下面我们来使用java的动态编译。有关java动态编译的API都在ls包中
一、使用JavaCompiler接口来编译java源程序(最简单的)
使用Java API来编译Java源程式有非常多方法,目前让我们来看一种最简单的方法,通过JavaCompiler进行编译。
我们能通过ToolProvider类的静态方法getSystemJavaCompiler来得到一个JavaCompiler接口的实例。
JavaCompiler compiler = SystemJavaCompiler();
JavaCompiler中最核心的方法是run。通过这个方法能编译java源程序。这个方法有3个固定参数和1个可变参数(可变参数是从Jave SE5开始提供的一个新的参数类型,用type… argu表示)。前3个参数分别用来为java编译器提供参数、得到Java编译器的输出信息及接收编译器的错误信息,后面的可变参数能传入一个或多个Java源程式文件。如果run编译成功,返回0。
int run(InputStream in, OutputStream out, OutputStream err, arguments) 如果前3个参数传入的是null,那么run方法将以标准的输入、输出代替,即System.in、System.out和。如果我们要编译一个hello.java文件,并将使用标准输入输出,run 的使用方法如下:
int results = tool.run(null, null, null, "Hello.java");
完整代码如下(用的是eclip工具)
1:eclip下工程截图
2.Hello.java(首先写好这个java文件,用来演示动态编译Hello.java文件) inhua.hello;
public class Hello{
public static void main(String[] args){
System.out.println("helloworld!");
}
}
3 DynamicCompileTest.java
st;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
买笔记本电脑要看哪些参数import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.Arrays;
ls.JavaCompiler;
ls.StandardJavaFileManager;
ls.ToolProvider;
ls.JavaCompiler.CompilationTask;
public class DynamicCompileTest {
public static void main(String[] args) throws Exception {
JavaCompiler javaCompiler = SystemJavaCompiler();
int result=javaCompiler.run(null, null,null,"-d","./temp","./temp/Hello.java");
System.out.println(result==0?"恭喜编译成功!":"对不起编译失败");节日灯笼
//在程序中来运行Hello.classs
Runtime Runtime();
Process ("java -cp ./inhua.hello.Hello"); InputStream
InputStream();
BufferedReader reader=new BufferedReader(new InputStreamReader(in));
String info="";
while((adLine())!=null){
S ystem.out.println(info);
}
}
}
二、使用StandardJavaFileManager编译Java源程序
在第一部分我们讨论调用java编译器的最容易的方法。这种方法能非常好地工作,但他确不能更有效地得到我们所需要的信息,如标准的输入、输出信息。而在Java SE6中最佳的方法是使用StandardJavaFileManager类。这个类能非常好地控制输入、输出,并且能通过DiagnosticListener得到诊断信息,而DiagnosticCollector类就是listener的实现。
使用StandardJavaFileManager需要两步。首先建立一个DiagnosticCollector实例及通过JavaCompiler的getStandardFileManager()方法得到一个StandardFileManager对象。最后通过CompilationTask中的call方法编译源程序
每个类的具体方法参数可以查看ja6 API文档。上面有很详细的解释
完整代码:
1:工程截图
2: DynamicCompileTest.java
st;
import java.io.File;
import java.io.FileWriter;
import java.util.Arrays;
ls.JavaCompiler;
ls.StandardJavaFileManager;
ls.ToolProvider;
ls.JavaCompiler.CompilationTask;
public class DynamicCompileTest {
public static void main(String[] args) throws Exception {
//1.创建需要动态编译的代码字符串
String nr="\r\n";//回车换行
String source="inhua.hello;"+nr+
" public class Hello{"+nr+
" public static void main(String[] args){"+nr+
" System.out.println(\"helloworld!\");"+nr+
"}"+nr+
"}";
心理与健康//2.将预动态编译的代码写入文件中1:创建临时目录2:写入临时文件
File dir=new Property("ur.dir")+"/temp");//临时目录//如果/temp目录不存在创建temp目录
如何包花
if(!ists()){
dir.mkdir();
}
FileWriter writer=new FileWriter(new File(dir,"Hello.java"));
writer.write(source);//将字符串写入文件中
writer.flush();
writer.clo();
//3:取得当前系统java编译器
希望英语怎么说JavaCompiler SystemJavaCompiler();
//4:获取一个文件管理器StandardJavaFileManage
StandardJavaFileManager
StandardFileManager(null, null, null);
//5.文件管理器根与文件连接起来
Iterable JavaFileObjects(new File(dir,"Hello.java"));
//6.创建编译的任务
丝瓜怎么做CompilationTask Task(null,
javaFileManager,null,Arrays.asList("-d","./temp"), null, it);
//执行编译
task.call();
javaFileManager.clo();
}
}
二、从内存中动态编译java程序
JavaCompiler不仅能编译硬盘上的Java文件,而且还能编译内存中的Java代码,然后使用reflection来运行他们。我们能编写一个类,通过这个类能输入Java原始码。一但建立这个对象,你能向其中输入任意的Java代码,然后编译和运行。
完整代码:
1:工程截图
2:JavaStringObject.java
st;
import java.io.IOException;
import java.URI;
ls.SimpleJavaFileObject;
public class JavaStringObject extends SimpleJavaFileObject {
private String code;
public JavaStringObject(String name, String code) {
//ate("string:///" + place('.', '/') +
sion), Kind.SOURCE);
ate(name+".java"), Kind.SOURCE);
}
@Override
public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
return code;
}
}
3: DynamicCompileTest.java
st;
import java.io.PrintWriter;
import java.io.StringWriter;
import flect.Method;
import java.URL;
import java.URLClassLoader;
import java.util.Arrays;
ls.JavaCompiler;
ls.JavaFileObject;
ls.ToolProvider;
ls.JavaCompiler.CompilationTask;
public class DynamicCompileTest {
public static void main(String[] args) throws Exception {
/*
* 编译内存中的java代码
*/
// 将代码写入内存中
StringWriter writer = new StringWriter();// 内存字符串输出流
PrintWriter out = new PrintWriter(writer);
out.println("inhua.hello;");
out.println("public class Hello{");
out.println("public static void main(String[] args){");
郭待封out.println("System.out.println(\"helloworld!\");");奶牛用英语怎么说
out.println("}");
out.println("}");
out.flush();
out.clo();