JAVA 的动态编译

杨颙
• 阅读 144

6.0引入了动态编译机制,也就是说,你利用java的io流把完整的程序代码写入.java后缀的文件,可以实现载入动态的实现载入,动态代理就是利用了此机制完成的。

javax.tools

Interface JavaCompiler

Java下面假设在D盘根目录下有一个hello.java文件(实际上此文件多数时候应该由java创建):

编译步骤:

1、调用 ToolProvider的getSystemJavaCompiler()方法,返回JavaCompiler

2、使用JavaCompiler的getStandardFileManager([url=]DiagnosticListener[/url]<? super[url=]JavaFileObject[/url]> diagnosticListener, [url=]Locale[/url]locale, [url=]Charset[/url] charset)方法,获取一个[url=]StandardJavaFileManager[/url]

3.把获取的[url=]StandardJavaFileManager[/url]传入 getTask([url=]Writer[/url] out, [url=]JavaFileManager[/url] fileManager, [url=]DiagnosticListener[/url]<? super [url=]JavaFileObject[/url]> diagnosticListener, [url=]Iterable[/url]<[url=]String[/url]> options,[url=]Iterable[/url]<[url=]String[/url]> classes,[url=]Iterable[/url]<? extends [url=]JavaFileObject[/url]> compilationUnits) 方法获得 [url=]JavaCompiler.CompilationTask[/url]

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

JavaCompiler.CompilationTask getTask(Writer out, JavaFileManager fileManager, DiagnosticListener<? super JavaFileObject> diagnosticListener, Iterable<String> options, Iterable<String> classes, Iterable<? extends JavaFileObject> compilationUnits) Creates a future for a compilation task with the given components and arguments. The compilation might not have completed as described in the CompilationTask interface.

使用给定的参数或者组件创建一个(未来使用)的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
为[url=]StandardJavaFileManager[/url] 创建一个实例
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:

  diagnosticListener - a diagnostic listener for non-fatal diagnostics; ifnull use the compiler's default method for reporting diagnostic

locale - the locale to apply when formatting diagnostics; null means the [url=]default locale[/url].charset - the character set used for decoding bytes; if null use the platform defaultReturns:the standard file manager

点赞
收藏
评论区
推荐文章
Wesley13 Wesley13
3年前
java 反射
一、java的动态性反射机制动态编译动态执行JavaScript代码动态字节码操作二、动态语言动态语言   程序运行时,可以改变程序结构或变量类型,典型的语言:python、ruby、javascript等C,C,JAVA不是动态语言,java可以称之为“准动态性语言”。但java
Wesley13 Wesley13
3年前
java中的反射和代理
  Java反射机制可以动态地获取类的结构,动态地调用对象的方法,是java语言一个动态化的机制。java动态代理可以在不改变被调用对象源码的前提下,在被调用方法前后增加自己的操作,极大地降低了模块之间的耦合性。这些都是java的基础知识,要想成为一名合格的程序猿,必须掌握!Java反射机制 JAVA反射机制是在运行状态中,对于任意一个类,都能够知
Wesley13 Wesley13
3年前
java的动态代理
1\.什么是动态代理代理模式是为了提供额外或不同的操作,而插入的用来替代”实际”对象的对象,这些操作涉及到与”实际”对象的通信,因此代理通常充当中间人角色。Java的动态代理比代理的思想更前进了一步,它可以动态地创建并代理并动态地处理对所代理方法的调用。在动态代理上所做的所有调用都会被重定向到单一的调用处理器上,它的工作是揭示调用的类型并确定相
lzy lzy
3年前
RPC框架手撕之路---java反射以及动态代理机制
在上一篇文章中,我们提到了,RPC框架所需要的java基础,第一点就是java的动态代理机制,动态代理机制的基础是反射,无论是在实际编程或者是面试时,都是java知识的重中之重。java反射:定义:在运行状态中,对于任意一个类,都能够知道这一个类的所有属性和方法,对于任意一个对象都能够通过反射机制调用一个类的任意方法,这种动态获取类信息以及动态调用类方法
Easter79 Easter79
3年前
Spring的两种代理JDK和CGLIB的区别浅谈
一、原理区别:java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP 2、如果目标对象实现了接口,可以
Wesley13 Wesley13
3年前
Java 动态代理机制分析及扩展,第 1 部分
引言Java动态代理机制的出现,使得Java开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类。代理类会负责将所有的方法调用分派到委托对象上反射执行,在分派执行的过程中,开发人员还可以按需调整委托类对象及其功能,这是一套非常灵活有弹性的代理框架。通过阅读本文,读者将会对Java动态代理机制有更加深入的理解
Easter79 Easter79
3年前
Spring的两种动态代理:Jdk和Cglib 的区别和实现
一、原理区别:java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP 2、如果目标对象实现了接口,可以
Wesley13 Wesley13
3年前
Java反射技术概述
1.什么是Java反射?  就是正在运行,动态获取这个类的所有信息2.反射机制的作用  a.反编译:.class.java  b.通过反射机制,访问Java对象的属性,方法,构造方法等3.反射机制的应用场景  Jdbc加载驱动  SpringIOC实现  Java框架4.创建对象的两种方式  a.直
Wesley13 Wesley13
3年前
Java动态代理机制解析
动态代理是指在运行时动态生成代理类。不需要我们像静态代理那个去手动写一个个的代理类。生成动态代理类有很多方式:Java动态代理,CGLIB,Javassist,ASM库等。这里主要说一下Java动态代理的实现。Java动态代理InvocationHandler接口Java动态代理中,每一个
Wesley13 Wesley13
3年前
Java提高班(六)反射和动态代理(JDK Proxy和Cglib)
反射和动态代理放有一定的相关性,但单纯的说动态代理是由反射机制实现的,其实是不够全面不准确的,动态代理是一种功能行为,而它的实现方法有很多。要怎么理解以上这句话,请看下文。一、反射反射机制是Java语言提供的一种基础功能,赋予程序在运行时<strong自省</strong(introspect,官方用语)的能力。通过反射我们可以直接
Wesley13 Wesley13
3年前
Java动态代理
jdk动态代理实现原理:利用字节码技术,生成新的class文件,来达到动态代理效果。新的class文件是怎么组织的?由于代理目标是接口,则通过实现接口和继续代理类来完成。看看下面的例子更容易明白。demo接口publicinterfacePeoPleInterface{