怎么样让网站快速收录,营销型网站建设的原则,可以免费做商业网站的cms,关于网站建设的实训报告java用什么编译器在上一篇文章中#xff0c;我写了关于如何在运行时生成代理的内容#xff0c;我们已经了解到生成Java源代码的程度。 但是#xff0c;要使用该类#xff0c;必须对其进行编译#xff0c;并将生成的字节码加载到内存中。 那是“编译”时间。 幸运的是… java用什么编译器 在上一篇文章中我写了关于如何在运行时生成代理的内容我们已经了解到生成Java源代码的程度。 但是要使用该类必须对其进行编译并将生成的字节码加载到内存中。 那是“编译”时间。 幸运的是从Java 1.6开始我们可以在运行时访问Java编译器因此可以将编译时与运行时混淆。 尽管在这种非常特殊的情况下这可能会导致过多的麻烦事情通常导致无法维护的自我修改代码但它可能还是有用的我们可以编译运行时生成的代理。 Java编译器API Java编译器读取源文件并生成类文件。 将它们组装到JARWAREAR和其他软件包中是另一种工具的责任。源文件和类文件不一定是驻留在磁盘SSD或内存驱动器中的真实操作系统文件。 毕竟当涉及到运行时API时Java通常对于抽象是很好的现在就是这种情况。 这些文件是一些“抽象”文件您必须通过API提供访问这些文件这些文件可以是磁盘文件但同时几乎可以是任何其他文件。 将源代码保存到磁盘上只是为了让编译器在同一进程中运行以将其读回并在类文件准备好后对其进行相同操作通常会浪费资源。 Java编译器作为运行时可用的API要求您提供一些简单的API或您喜欢的SPI来访问源代码并发送生成的字节码。 如果我们在内存中有代码则可以有以下代码 来自此文件 public Class? compile(String sourceCode, String canonicalClassName)throws Exception {JavaCompiler compiler ToolProvider.getSystemJavaCompiler();ListJavaSourceFromString 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.htmljava用什么编译器