JAVA 6.0引入了动态编译机制,也就是说,你利用java的io流把完整的程序代码写入.java后缀的文件,可以实现载入动态的实现载入,动态代理就是利用了此机制完成的。
javax.tools
Interface JavaCompiler
下面假设在D盘根目录下有一个hello.java文件(实际上此文件多数时候应该由java创建):
编译步骤:
1、调用 ToolProvider的getSystemJavaCompiler()方法,返回JavaCompiler
2、使用JavaCompiler的getStandardFileManager(DiagnosticListener<? superJavaFileObject> diagnosticListener, Locale locale, Charset charset)方法,获取一个StandardJavaFileManager
3.把获取的StandardJavaFileManager传入 getTask(Writer out, JavaFileManager fileManager, DiagnosticListener<? super JavaFileObject> diagnosticListener, Iterable<String> options,Iterable<String> classes,Iterable<? extends JavaFileObject> compilationUnits) 方法获得 JavaCompiler.CompilationTask
4、激活task 即可 task.call();这样文件编译成功了,稍显麻烦。
package test.javaComplile;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
public class Test {
/**
* @param args
* @throws IOException
* @throws IllegalAccessException
* @throws InstantiationException
* @throws ClassNotFoundException
*/
public static void main(String[] args) throws IOException, InstantiationException, IllegalAccessException, ClassNotFoundException {
// TODO Auto-generated method stub
JavaCompiler complier = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager sjf =
complier.getStandardFileManager(null, null, null);
Iterable it = sjf.getJavaFileObjects("D:\\hello.java");
CompilationTask task = complier.getTask(null, sjf, null, null, null, it);
task.call(); //调用创建
sjf.close();
URL urls[] = new URL[]{ new URL("file:/D:/")}; //储存文件目录的地址
URLClassLoader uLoad = new URLClassLoader(urls); //classloader从哪个目录找?
Class c = uLoad.loadClass("hello"); //找哪个class文件 注意不带后缀名
c.newInstance(); //创建一个实例
}
}
output:
Hello world!
API解释:
Interface JavaCompiler
使用给定的参数或者组件创建一个(未来使用)的CompilationTask 。如CompilationTask 接口所述,编译有可能没有完成。
If a file manager is provided, it must be able to handle all locations defined in StandardLocation.
如果提供了file manager ,他一定能处理所有地方。
Note that annotation processing can process both the compilation units of source code to be compiled, passed with the compilationUnits parameter, as well as class files, whose names are passed with the classes parameter.
Parameters:
out - a Writer for additional output from the compiler; use System.err if null定义Writer类型输出流 ,null使用System.err输出流
fileManager - a file manager; if null use the compiler's standard filemanager定义fileManager,null使用编译器标准
fileManagerdiagnosticListener - a diagnostic listener; if null use the compiler's default method for reporting diagnostics定义diagnosticListener(诊断监听器)
options - compiler options, null means no options
classes - names of classes to be processed by annotation processing, null means no class names注解类
compilationUnits - the compilation units to compile, null means no compilation units
Returns:
an object representing the compilation
Throws:
RuntimeException - if an unrecoverable error occurred in a user supplied component. The cause will be the error in user code. IllegalArgumentException - if any of the given compilation units are of other kind than source
getStandardFileManager
The standard file manager will be automatically reopened if it is accessed after calls toflush
or close
. The standard file manager must be usable with other tools.
-
Parameters:
-
locale
- the locale to apply when formatting diagnostics;null
means the default locale. -
charset
- the character set used for decoding bytes; ifnull
use the platform default
Returns:
- the standard file manager
diagnosticListener
- a diagnostic listener for non-fatal diagnostics; ifnull
use the compiler's default method for reporting diagnostic