Java用Java编译

在上一篇文章中,我写了关于如何在运行时生成代理的信息,我们已经了解到生成Java源代码的程度。 但是,要使用该类,必须对其进行编译,并将生成的字节码加载到内存中。 那是“编译”时间。 幸运的是,从Java 1.6开始,我们可以在运行时访问Java编译器,因此可以将编译时与运行时混淆。 尽管在这种非常特殊的情况下,尽管这可能会导致太多麻烦的事情,通常会导致无法维护的自我修改代码,但它可能还是有用的:我们可以编译运行时生成的代理。

Java编译器API

Java编译器读取源文件并生成类文件。 (将它们组装到JAR,WAR,EAR和其他软件包中是另一种工具的责任。)源文件和类文件不一定是驻留在磁盘,SSD或内存驱动器中的真实操作系统文件。 毕竟,当涉及到运行时API时,Java通常对于抽象是很好的,现在就是这种情况。 这些文件是一些“抽象”文件,您必须通过API提供访问这些文件,这些文件可以是磁盘文件,但同时几乎可以是任何其他文件。 将源代码保存到磁盘上只是为了让编译器在相同的进程中运行以将其读回并在类文件准备就绪时对其进行相同的处理,通常会浪费资源。

Java编译器作为运行时可用的API,要求您提供一些简单的API(或您所称的SPI)来访问源代码并发送生成的字节码。 如果我们在内存中有代码,则可以有以下代码( 来自此文件 ):

public Class<?> compile(String sourceCode, String canonicalClassName)throws Exception {JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();List<JavaSourceFromString> sources = new LinkedList<>();String className = calculateSimpleClassName(canonicalClassName);sources.add(new JavaSourceFromString(className, sourceCode));StringWriter sw = new StringWriter();MemoryJavaFileManager fm = new MemoryJavaFileManager(compiler.getStandardFileManager(null, null, null));JavaCompiler.CompilationTask task = compiler.getTask(sw, fm, null,null, null, sources);Boolean compilationWasSuccessful = task.call();if (compilationWasSuccessful) {ByteClassLoader byteClassLoader = new ByteClassLoader(new URL[0],classLoader, classesByteArraysMap(fm));Class<?> klass = byteClassLoader.loadClass(canonicalClassName);byteClassLoader.close();return klass;} else {compilerErrorOutput = sw.toString();return null;}}
  • 该代码是开源项目Java源代码编译器(jscc)的一部分 ,位于文件Compiler.java中 。

编译器实例可通过ToolProvider并且要创建编译任务,我们必须调用getTask() 。 该代码通过字符串编写器将错误写入字符串。 文件管理器( fm )是在同一程序包中实现的,它只是将文件作为字节数组存储在映射中,其中的键是“文件名”。 这是类加载器在稍后加载类时将获取字节的位置。 该代码不提供任何可诊断的侦听器(请参见RT中Java编译器的文档),编译器选项或注释处理器要处理的类。 这些都是空值。 最后一个参数是要编译的源代码列表。 我们在此工具中仅编译一个类,但是由于编译器API是通用的并且需要可迭代的源,因此我们提供了一个列表。 由于存在另一种抽象级别,因此此列表包含JavaSourceFromString

要开始编译,必须“调用”创建的任务,如果编译成功,则从一个或多个生成的字节数组中加载类。 请注意,如果在我们编译的顶级类中有嵌套类或内部类,则编译器将创建几个类。 这就是为什么即使只编译一个源类,我们也必须维护类的整个映射,而不是单个字节数组。 如果编译不成功,则错误输出将存储在字段中并可以查询。

该类的使用非常简单,您可以在单元测试中找到示例:

private String loadJavaSource(String name) throws IOException {InputStream is = this.getClass().getResourceAsStream(name);byte[] buf = new byte[3000];int len = is.read(buf);is.close();return new String(buf, 0, len, "utf-8");}
...@Testpublic void given_PerfectSourceCodeWithSubClasses_when_CallingCompiler_then_ProperClassIsReturned()throws Exception {final String source = loadJavaSource("Test3.java");Compiler compiler = new Compiler();Class<?> newClass = compiler.compile(source, "com.javax0.jscc.Test3");Object object = newClass.newInstance();Method f = newClass.getMethod("method");int i = (int) f.invoke(object, null);Assert.assertEquals(1, i);}

请注意,以这种方式创建的类仅在运行时可用于代码。 例如,您可以创建对象的不可变版本。 如果要在编译期间提供可用的类,则应使用scriapt之类的注释处理器。

翻译自: https://www.javacodegeeks.com/2016/03/java-compile-java.html

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

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

相关文章

PHP实现前台页面与MySQL的数据绑定、同步更新

今天我来给大家介绍一个PHP-MySQL的小项目。 使用 PHP和前台Ajax 实现在前台对MySQL数据库中数据的增、删等操作语句功能。 如果有问题&#xff0c;欢迎拍砖~ 有不懂的地方&#xff0c;提出来咱们一起探讨~ 首先&#xff0c;我们先做好前台HTML、CSS样式&#xff0c;代码如下&a…

如何用Vue实现简易的富文本编辑器,并支持Markdown语法

前端开发经常会用到富文本编辑器&#xff0c;比如CKEditor&#xff0c;动不动一个库几十M的代码量&#xff0c;其中涉及许多你可能用不到的功能特性和相关设置&#xff0c;CKEditor最新版本的代码仓库就有接近2000个JS文件&#xff0c;300,000行代码。 可是如果你只需要一个简…

互联网基建成果,快速实现一个clubhouse要多久

最近国外的一款基于语音的社交软件clubhouse掀起了一股热潮&#xff0c;尤其是在Eleon Musk的带动下&#xff0c;整个互联网圈内人都在第一时间抢先体验。不管它为什么会火&#xff0c;肯定不是技术上有什么特别的优势。随着整个互联网技术生态的不断发展&#xff0c;互联网基础…

阿里帝国到底有多庞大

马云&#xff0c;男&#xff0c;1964年9月10日生于浙江省杭州市&#xff0c;祖籍浙江省嵊州市谷来镇&#xff0c; 阿里巴巴集团主要创始人&#xff0c;现担任阿里巴巴集团董事局主席、日本软银董事、TNC中国理事会主席兼全球董事会成员、华谊兄弟董事、生命科学突破奖基金会董事…

resteasy 统一异常_RESTEasy教程第3部分:异常处理

resteasy 统一异常在开发软件应用程序时&#xff0c;异常处理是显而易见的要求。 如果在处理用户请求时发生任何错误&#xff0c;我们应该向用户显示一个错误页面&#xff0c;其中包含详细的异常消息&#xff0c;错误代码&#xff08;可选&#xff09;&#xff0c;更正输入和重…

哪些网站在+1s后有神奇的功能

1s 有些网站&#xff0c;当我们给它 1s 时&#xff0c;会有意想不到的奇效。 github 1s 在 GitHub 域名后面加 1s 可以直接使用 vscode online 打开仓库代码&#xff0c;例如 https://github1s.com/fantingsheng/front-end https://github1s.com/fantingsheng/front-end^^ …

如何搭建一个内部组件共享平台

如今前端越来越趋于组件化的开发方式&#xff0c;最大的益处就是UI页面和逻辑的共用。在开发者的眼里&#xff0c;如果你打开一个网站&#xff0c;组件化的开发方式会让你看起来像这个样子&#xff1a;逻辑功能上我们会封装成一个库&#xff0c;然后NPM发布到公共仓库上&#x…

标准C程序设计七---46

Linux应用 编程深入 语言编程标准C程序设计七---经典C11程序设计 以下内容为阅读&#xff1a; 《标准C程序设计》&#xff08;第7版&#xff09; 作者&#xff1a;E. Balagurusamy&#xff08;印&#xff09;&#xff0c; 李周芳译 清华大学出版社…

不要讨厌HATEOAS

或我如何学会不再担心和爱HATEOAS REST已成为实现Web服务的事实上的解决方案&#xff0c;至少已成为一种流行的解决方案。 这是可以理解的&#xff0c;因为REST在使用HTTP规范时提供了一定程度的自我文档。 它经久耐用&#xff0c;可扩展&#xff0c;并提供了其他一些理想的特…

前端如何进行日志驱动开发

日志在开发过程中的作用自不必说&#xff0c;一旦程序出现问题&#xff0c;我们首先想到的是通过日志监控去追查。 好的日志可以通过应用程序执行的历史记录模拟出用户在使用程序的时候操作的完整过程。 想知道发生了什么 为了便于我们分析程序哪里出现问题&#xff0c;我们…

消息钩子学习工程

前奏近来一直在自学Windows Hook相关的知识&#xff0c;已经尝试多种注入方式。尤其对消息钩子方式很感兴趣&#xff0c;因为看到Spy能够截获系统中绝大多数应用的消息流&#xff0c;就很想知道它的工作原理&#xff0c;打算制作属于自己的Spy。消息钩子简介&#xff1a;消息钩…

[Angular] 笔记 8:list/detail 页面以及@Input

1. list 页面 list/detail 是重要的 UI 设计模式。 vscode terminal 运行如下命令生成 detail 组件&#xff1a; PS D:\Angular\my-app> ng generate component pokemon-base/pokemon-detail --modulepokemon-base/pokemon-base.module.ts CREATE src/app/pokemon-base/p…

javaone_JavaOne 2012 – 2400小时! 一些建议

javaone您可能已经看到JavaOne 2012 Content Catalog在线。 计划委员会经过数周的紧张工作&#xff0c;对每个提案进行了分类&#xff0c;审查&#xff0c;评分和讨论&#xff0c;我们终于设法为您设置了&#xff08;希望如此&#xff09;有趣的组合。 整整105天或2400小时&…

推荐几个最近Star过的Github仓库

平时逛Github的时候&#xff0c;总是顺手对一些自己认为好的仓库给个 Star&#xff0c;一是对作者的鼓励&#xff0c;二来推荐给关注自己的人&#xff08;首页动态可见&#xff09;。 下面列举了一些我平时 Star 过的仓库&#xff0c;顺便也推荐给我的读者。 Front-End Checkli…

使用Gatling + Gradle + Jenkins Pipeline为您的JAX-RS(和JavaEE)应用程序进行连续压力测试...

在这篇文章中&#xff0c;我将解释如何使用Gatling项目为您的JAX-RS Java EE端点编写压力测试&#xff0c;以及如何将它们与Gradle和Jenkins Pipeline集成&#xff0c;因此&#xff0c;除了进行简单的压力测试外&#xff0c;您还可以使用以下方法&#xff1a; 连续的压力测试&a…

使用 VuePress 搭建一个自己的知识文档

最近准备对前端知识做一个梳理&#xff0c;将自己的平时遇到的问题和解决方案形成一个知识文档。本文记录了搭建 VuePress 的主要过程&#xff0c;同时也提供了部分自定义的配置&#xff0c;示例地址&#xff1a;http://doc.i-fanr.com 环境搭建 VuePress 有着比较完善的中文文…

代码重构学习

文章&#xff1a;浅谈重构中踩过的坑 文章中有一个很好的&#xff0c;优化if else多分支判断的例子&#xff0c;将方法抽象出来&#xff0c;根据不同场景实现抽象类&#xff0c;然后用写一个工厂类&#xff0c;一个工厂方法&#xff0c;通过传入类型&#xff0c;进行实例化。 很…

pta 朋友圈

某学校有N个学生&#xff0c;形成M个俱乐部。每个俱乐部里的学生有着一定相似的兴趣爱好&#xff0c;形成一个朋友圈。一个学生可以同时属于若干个不同的俱乐部。根据“我的朋友的朋友也是我的朋友”这个推论可以得出&#xff0c;如果A和B是朋友&#xff0c;且B和C是朋友&#…

金三银四跳槽面试季,我整理前端知识做了个网站

每年的金三银四&#xff0c;都将迎来求职面试的一个高峰期&#xff0c;为什么会有那么多的求职需求&#xff1f;多是因为以下几个来源&#xff1a;已拿 offer 等年终奖的&#xff1a;年前已经找到机会&#xff0c;领了年终奖辞职要到新公司报到的临时起意要辞及裸辞的&#xff…

web框架和后台开发_Web开发框架–第1部分:选项和标准

web框架和后台开发在我的公司&#xff0c;我们正在评估未来几年将使用哪种Web开发框架。 自上次评估以来&#xff0c;我们一直在使用由Struts 2驱动的Java应用服务器作为MVC&#xff0c;将Tiles作为模板引擎&#xff0c;将jQuery用于Javascript awesomennes&#xff0c;将DWR用…