java compile_java中的CompileAPI入门及使用

介绍

java5之前我们可以通过java提供的tools.jar来操作java编译器,java6提供了新的API,让我们可以更方便的调用。包名为javax.tools。

使用

通过文件编译

String filePath = "D:\\Client.java";

//获取java编译器

JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();

//编译

int result = javaCompiler.run(null, null, null, filePath);

System.out.println(result);

结果为0表示编译成功,在相同目录下生成了Client.class文件。

编译参数依次为

java编译器提供参数,如果为null,以System.in代替

得到Java编译器的输出信息,如果为null,以System.out代替

接收编译器的错误信息,如果为null,以System.err代替

一个或多个Java源程式文件

通过非文件格式编译

java还提供了编译其他形式的源文件的功能,如内存字符串文本,数据库读取的文本。

public class JavaFileManagerMain {

public static void main(String[] args) {

//文件路径

String fullQuanlifiedFileName = "D:\\Client.java";

//获取编译器

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

//获取文件管理器 参数依次为错误监听器,区域对象,编码

StandardJavaFileManager fileManager =

compiler.getStandardFileManager(null, null, null);

//通过文件全路径获取要编译的文件对象

Iterable extends JavaFileObject> files =

fileManager.getJavaFileObjectsFromStrings(

Arrays.asList(fullQuanlifiedFileName));

//创建编译任务 参数为错误输出流,文件管理器,错误处理器,编译器选项,参与编译的class,带编译的java文件

JavaCompiler.CompilationTask task = compiler.getTask(

null, fileManager, null, null, null, files);

//执行任务

Boolean result = task.call();

if (result) {

System.out.println("Succeeded");

}

}

}

接下来实现从内存中读取待编译对象

public class StringObject extends SimpleJavaFileObject {

private String content = null;

protected StringObject(String className, String contents) throws URISyntaxException {

super(new URI(className), Kind.SOURCE);

this.content = contents;

}

@Override

public CharSequence getCharContent(boolean ignoreEncodingErrors) {

return content;

}

}

public class StringClassCompilerMain {

public static void main(String[] args) {

JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();

StandardJavaFileManager standardJavaFileManager = javaCompiler.getStandardFileManager(null, null, null);

JavaFileObject testFile = generateTest();

Iterable extends JavaFileObject> classes = Arrays.asList(testFile);

JavaCompiler.CompilationTask task = javaCompiler.getTask(null, standardJavaFileManager, null, null, null, classes);

if (task.call()) {

System.out.println("success");

} else {

System.out.println("failure!");

}

}

//通过字符串创建一个待编译对象

private static JavaFileObject generateTest() {

String contents = "package com.imooc.sourcecode.java.javacompile.test3;" +

"class Test {\n" +

" public static void main(String[] args) {\n" +

" System.out.println(\"success\");\n" +

" }\n" +

"}\n";

StringObject so = null;

try {

so = new StringObject("com.imooc.sourcecode.java.javacompile.test3.Test", contents);

} catch (URISyntaxException e) {

e.printStackTrace();

}

return so;

}

}

结果编译成功。

实现在运行期编译及加载类

定义源代码存储类

/**

* 待编译对象 存储待编译的字符串

*/

public class JavaSourceFileObject extends SimpleJavaFileObject {

//表示java源代码

private CharSequence content;

protected JavaSourceFileObject(String className, String content) {

super(URI.create("string:///" + className.replaceAll("\\.", "/") + Kind.SOURCE.extension), Kind.SOURCE);

this.content = content;

}

/**

* 获取需要编译的源代码

*

* @param ignoreEncodingErrors

* @return

* @throws IOException

*/

@Override

public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {

return content;

}

}

定义编译结果存储类

/**

* 存储编译之后的class内容

*/

public class JavaTargetFileObject extends SimpleJavaFileObject {

/**

* Compiler编译后的byte数据会存在这个ByteArrayOutputStream对象中,

* 后面可以取出,加载到JVM中。

*/

private ByteArrayOutputStream byteArrayOutputStream;

public JavaTargetFileObject(String className, Kind kind) {

super(URI.create("string:///" + className.replaceAll("\\.", "/") + kind.extension), kind);

this.byteArrayOutputStream = new ByteArrayOutputStream();

}

/**

* 覆盖父类SimpleJavaFileObject的方法。

* 该方法提供给编译器结果输出的OutputStream。

*

* 编译器完成编译后,会将编译结果输出到该 OutputStream 中,我们随后需要使用它获取编译结果

*

* @return

* @throws IOException

*/

@Override

public OutputStream openOutputStream() throws IOException {

return this.byteArrayOutputStream;

}

/**

* FileManager会使用该方法获取编译后的byte,然后将类加载到JVM

*/

public byte[] getBytes() {

return this.byteArrayOutputStream.toByteArray();

}

}

定义自己的文件管理器

/**

* 内存文件管理器

* @see JavaTargetFileObject

*/

public class ClassFileManager extends ForwardingJavaFileManager {

/**

* 存储编译后的代码数据

*/

private JavaTargetFileObject classJavaFileObject;

protected ClassFileManager(JavaFileManager fileManager) {

super(fileManager);

}

/**

* 编译后加载类

*

* 返回一个匿名的SecureClassLoader:

* 加载由JavaCompiler编译后,保存在ClassJavaFileObject中的byte数组。

*/

@Override

public ClassLoader getClassLoader(Location location) {

return new SecureClassLoader() {

@Override

protected Class> findClass(String name) throws ClassNotFoundException {

byte[] bytes = classJavaFileObject.getBytes();

return super.defineClass(name, bytes, 0, bytes.length);

}

};

}

/**

* 给编译器提供JavaClassObject,编译器会将编译结果写进去

*/

@Override

public JavaFileObject getJavaFileForOutput(Location location, String className, JavaFileObject.Kind kind, FileObject sibling)

throws IOException {

this.classJavaFileObject = new JavaTargetFileObject(className, kind);

return this.classJavaFileObject;

}

}

定义一个实现类编译和加载

/**

* 运行时编译

*/

public class DynamicCompiler {

private JavaFileManager fileManager;

public DynamicCompiler() {

this.fileManager = initManger();

}

private JavaFileManager initManger() {

if (fileManager != null) {

return fileManager;

} else {

JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();

DiagnosticCollector diagnosticCollector = new DiagnosticCollector<>();

fileManager = new ClassFileManager(javaCompiler.getStandardFileManager(diagnosticCollector, null, null));

return fileManager;

}

}

/**

* 编译源码并加载,获取Class对象

*

* @param fullName

* @param sourceCode

* @return

* @throws ClassNotFoundException

*/

public Class compileAndLoad(String fullName, String sourceCode) throws ClassNotFoundException {

JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler();

List javaFileObjectList = new ArrayList<>();

javaFileObjectList.add(new JavaSourceFileObject(fullName, sourceCode));

boolean result = javaCompiler

.getTask(null, fileManager, null, null, null, javaFileObjectList)

.call();

if (result) {

return this.fileManager.getClassLoader(null).loadClass(fullName);

} else {

return Class.forName(fullName);

}

}

/**

* 关闭fileManager

*

* @throws IOException

*/

public void close() throws IOException {

this.fileManager.close();

}

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/260341.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《Two Days DIV + CSS》读书笔记——CSS选择器

1.1.2 CSS选择器 CSS 选择器最基本的有四种&#xff1a;标签选择器、ID 选择器、类选择器、通用选择器。 【标签选择器】 一个完整的 HTML 页面由很多不同的标签组成&#xff0c;而标签选择器&#xff0c;则是决定哪些标签采用相应的 CSS 样式&#xff0c;比如&#xff0c;在 s…

TempDB为什么要根据CPU数目来决定文件个数

在SQL Server的世界中&#xff0c;SQL Server在Windows之上有一套自己的任务调度和资源分配系统&#xff0c;这使得SQL Server作为Windows的一个进程&#xff0c;却可以处理大量的并发&#xff0c;这些任务调度和资源分配非常像一个操作系统&#xff0c;因此SQL Server在Window…

python基础到实践_一本书搞定Python入门到实践

题图&#xff1a;Photo by Aaron Burden on Unsplash上周介绍了几本Python从入门到进阶书籍&#xff0c;今天推荐一本入门好书《Python编程&#xff1a;从入门到实践》&#xff0c;适合零基础小白&#xff0c;也适合有其它语言背景的程序员。书中有哪些亮点&#xff1f;2016年出…

Linux网卡eth0变成eth1修改方法

由于换了主板&#xff0c;集成网卡mac地址变了&#xff0c;70-persistent-net.rules中仍然保留了老网卡的内容&#xff0c;新网卡则被识别为eth1。 将表示老网卡的行注释掉&#xff0c;然后将表示新网卡的行中eth1改成eth0&#xff0c;在把网卡配置文件ifcfg-eth0的mac地址改成…

java微博模拟登陆_java 模拟登录新浪微博(通过cookie)

这几天一直在研究新浪微博的爬虫&#xff0c;发现爬取微博的数据首先要登录。本来打算是通过账号和密码模拟浏览器登录。但是现在微博的登录机制比较复杂。通过账号密码还没有登录成功QAQ。所以就先记录下&#xff0c;通过cookie直接访问自己的微博主页。微博登录的认证过程微博…

硬盘结构,主引导记录MBR,硬盘分区表DPT,主分区、扩展分区和逻辑分区,电脑启动过程...

filex的文件系统看的云里雾里&#xff0c;还是先总结下FAT的一些基本知识吧。硬盘结构硬盘有很多盘片组成&#xff0c;每个盘片的每个面都有一个读写磁头。如果有N个盘片。就有2N个面&#xff0c;对应2N个磁头(Heads)&#xff0c;从0、1、2开始编号。每个盘片的半径均为固定值R…

最全面 Nginx 入门教程 + 常用配置解析

转自 http://blog.csdn.net/shootyou/article/details/6093562 Nginx介绍和安装 一个简单的配置文件 模块介绍 常用场景配置 进阶内容 参考资料 Nginx介绍和安装 Nginx是一个自由、开源、高性能及轻量级的HTTP服务器及反转代理服务器&#xff0c; 其性能与IMAP/POP3代理服务器…

linux 客户机中不支持 unity_婚姻中的不理解,来源于夫妻双方情感支持的不同

很多女性在婚姻中往往觉得无法得到丈夫的理解&#xff0c;当遇到一些生活或者工作上的问题的时候&#xff0c;她们想要在情感上得到丈夫的支持和理解。但是很多丈夫对此可能并不了解和理解&#xff0c;更倾向于用理性帮助妻子解决问题。而女性所需要的帮助可能并不是解决问题的…

Linux中使用crontab命令启用自定义定时任务

一 简介Linux下的任务调度分为两类&#xff0c;系统任务调度和用户任务调度系统任务调度&#xff1a;系统需要定期执行的任务&#xff0c;比如重启、日志清理等&#xff0c;其配置文件是&#xff1a;/etc/crontab用户任务调度&#xff1a;某个用户需要定期执行的任务。用户可以…

java 循环标记_深入浅析Java 循环中标签的作用

continue和break可以改变循环的执行流程&#xff0c;但在多重循环中&#xff0c;这两条语句无法直接从内层循环跳转到外层循环。在C语言中&#xff0c;可以通过goto语句实现多重循环的跳转&#xff0c;但在非循环结构中使用goto语句会使程序的结构紊乱&#xff0c;可读性变差。…

JS,Jquery 调用 C#WebService

1&#xff0c;需要在服务下面把代码的注释去掉 // 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务&#xff0c;请取消对下行的注释。   //[System.Web.Script.Services.ScriptService] 2,JS 调用方法如下 var request <?xml version"1.0" encoding"…

iOS tabview 适配问题

ios7的UITableView实现ios6的圆角效果 iOS7 UITableView做成类似iOS6风格 在iOS7的时候我们会发现cell的默认线条会向右偏移&#xff0c;使左边空出了一些位置&#xff0c;这时候我们可以调用如下的方法来解决。这样我们的cell就会和iOS6前的一样铺满整个宽度了。 if ([tableVi…

PHP学习总结(14)——PHP入门篇之常用运算符

一、什么是运算符什么是运算符&#xff1f;运算符是告诉PHP做相关运算的标识符号。例如&#xff0c;你需要计算123乘以456等于多少&#xff0c;这时候就需要一个符号&#xff0c;告诉服务器&#xff0c;你需要做乘法运算。PHP中的运算符有哪些&#xff1f;PHP运算符一般分为算术…

百度时间显示_文章的发布时间对百度优化网站重要吗

文章的发布时间对百度优化网站重要吗&#xff1f;这个问题&#xff0c;相信很多初做网站优化的萌新朋友都会问到&#xff0c;以小匠个人的经历来分享这个问题的经验&#xff0c;小匠认为&#xff0c;文章的发布时间对优化网站是非常重要的&#xff0c;下面小匠将从实际经历来给…

循环链表解决约瑟夫环问题

约瑟夫环问题可以简单的使用数组的方式实现&#xff0c;但是现在我使用循环链表的方法来实现&#xff0c;因为上午看到一道面试题规定使用循环链表解决约瑟夫环问题。 什么是约瑟夫环&#xff1f; “约瑟夫环是一个数学的应用问题&#xff1a;已知n个人&#xff08;以编号1&…

java 什么时候进行垃圾回收_java什么时候进行垃圾回收,垃圾回收的执行流程

java的垃圾回收分为三个区域新生代 老年代 永久代一个对象实例化时 先去看伊甸园有没有足够的空间如果有 不进行垃圾回收 ,对象直接在伊甸园存储.如果伊甸园内存已满,会进行一次minor gc然后再进行判断伊甸园中的内存是否足够如果不足 则去看存活区的内存是否足够.如果内存足够…

常用的webservice接口

商业和贸易&#xff1a; 1、股票行情数据 WEB 服务&#xff08;支持香港、深圳、上海基金、债券和股票&#xff1b;支持多股票同时查询&#xff09; Endpoint: http://webservice.webxml.com.cn/WebServices/StockInfoWS.asmx Disco: http://webservice.webxml.com.cn/WebServ…

基于HTML5 Canvas 实现矢量工控风机叶轮旋转

之前在拓扑上的应用都是些静态的图元&#xff0c;今天我们将在拓扑上设计一个会动的图元——叶轮旋转。 先看看最后我们实现的效果&#xff1a;http://www.hightopo.com/demo/fan/index.html 我们先来看下这个叶轮模型长什么样 从模型上看&#xff0c;这个叶轮模型有三个叶片&a…

java 并发模型总类_java并发编程系列-内存模型基础

java线程之间的通信对程序开发人员是完全透明的&#xff0c;内存的可见性问题很容易困扰很多开发人员。本篇博文将揭开java内存模型的神秘面纱&#xff0c;来看看内存模型到底是怎样的。并发编程模型的分类并发编程中需要处理的两个关键问题&#xff1a;线程之间如何通信线程之…

python调用java的jar包_python调用java的jar包报错127

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼最近在弄python需要调用到Java的jar包&#xff0c;按照网上的教程走&#xff0c;最后总是报错No matching overloads found for [init in find. at native\common\jp_method.cpp:127Java&#xff1a;package aes;import com.sun.cr…