TestJavaCompiler.java 通过java compile api生成class import javax.tools.JavaCompiler; import javax.tools.JavaFileObject "}"; public static void main(String[] args) throws Exception { // 获取当前平台编译器 JavaCompiler TestJavaCompilerMemory.java 测试 import javax.tools.JavaCompiler; import javax.tools.JavaFileObject; import "}"; public static void main(String[] args) throws Exception { // 获取当前平台编译器 JavaCompiler "}"; public static void main(String[] args) throws Exception { // 获取当前平台编译器 JavaCompiler
IDEA 自动重置 Language level 导致与 JavaCompiler 版本不一致问题 问题描述 使用 IDEA 开发 Java 项目的时候, Java 语言使用 1.8 版本
JavaCompiler 由于 Config.java 是在运行时生成的,所以编译也只能在运行时了,万幸 Java 有提供 javax.util.JavaCompiler 类进行 Java 类的动态编译 JavaCompiler 的典型应用示例如下: JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler(); JavaFileManager fileManager = javaCompiler.getStandardFileManager(null, null, null); CompilationTask task = javaCompiler.getTask(out, fileManager, diagnosticListener, options, classes, compilationUnits 委托模式 由于 JavaCompiler 的默认实现都是通过文件进行的,这不符合我的期望,我需要的是输入和输出都在内存进行,所以需要修改 JavaCompiler 的实现,JavaCompiler、JavaFileManager
文章目录 Code 分析 修复 Code package com.artisan.jsr269; import javax.tools.JavaCompiler; import javax.tools.StandardJavaFileManager new FileWriter(file); fw.write(src); fw.flush(); fw.close(); // 使用JavaCompiler 编译java文件 // 获取系统Java编译器 JavaCompiler jc = ToolProvider.getSystemJavaCompiler(); Iterable fileObjects = fileManager.getJavaFileObjects(filename); // 创建编译任务 JavaCompiler.CompilationTask (JavaCompiler.java:1170) at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:856)
其实JDK的底层本身就提供了动态加载类文件的能力,它就是JavaCompiler。 如果使用JavaCompiler动态加载类文件内容,那就需要经过下述流程: 把Java代码组装成一个格式正确的java源码,编译为class字节流 利用ClassLoader将class字节流加载进入JVM ,得到对应的class 基于class则可以反射调用对应的逻辑 JavaCompiler的标准工作流程 如果代码片段格式正确,我们就通过Java编译器动态编译源代码得到了class。 javaCompiler = ToolProvider.getSystemJavaCompiler(); // 文件管理器 StandardJavaFileManager standardFileManager = javaCompiler.getStandardFileManager(null, null, null); JavaFileManager fileManager
JavaCompiler 从程序中调用 Java™ 编程语言编译器的接口。 JavaCompiler.CompilationTask 表示编译任务的 future 的接口 JavaFileManager 在 Java™ 编程语言源和类文件之上进行操作的工具的文件管理器 JavaCompiler 为编译器的接口,个人觉得其是包的核心,我们会通过下面的方式,获取编译器 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler (); JavaCompiler.CompilationTask 表示编译任务的未来的接口。 JavaFileManager内容管理器,在JavaCompiler的getTask方法中,我们需要传入该参数。
import java.io.File;import java.io.FileWriter;import javax.tools.JavaCompiler;import javax.tools.JavaCompiler.CompilationTask FileWriter(file); fw.write(javaCode); fw.flush(); fw.close(); // JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager standardFileManager = javaCompiler.getStandardFileManager(null, null, null); Iterable<? = standardFileManager.getJavaFileObjects(fileName); // 执行编译任务 CompilationTask task = javaCompiler.getTask
JAVA API提供了相应的工具(JavaCompiler)来实现动态编译。下面我们通过一个简单的例子介绍,如何通过JavaCompiler实现java代码动态编译。 ? 1 ▼ 获取JavaCompiler ? 获取JDK提供的java编译器,如果没有提供编译器,则返回null; 2 ▼ 编译 ?
String path1 = "/path/to/LamdbaTest1.java"; String path2 = "/path/to/LamdbaTest2.java"; JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler(); DiagnosticCollector diagnostics = new DiagnosticCollector (); StandardJavaFileManager fileManager = javaCompiler.getStandardFileManager(diagnostics, null fileManager.getJavaFileObjects( new File(path1), new File(path2) ); JavaCompiler.CompilationTask task = javaCompiler.getTask(null, fileManager, diagnostics, null, null, compilationUnits
这可以通过调用javac命令行工具或者使用Java API中的编译器API(如javax.tools.JavaCompiler)来实现。 生成字节码: 编译过程会生成字节码文件(.class文件)。 Code package com.artisan.jsr269; import javax.tools.JavaCompiler; import javax.tools.StandardJavaFileManager new FileWriter(file); fw.write(src); fw.flush(); fw.close(); // 使用JavaCompiler 编译java文件 // 获取系统Java编译器 JavaCompiler jc = ToolProvider.getSystemJavaCompiler(); Iterable fileObjects = fileManager.getJavaFileObjects(filename); // 创建编译任务 JavaCompiler.CompilationTask
核心对象:1 JavaCompiler 2 StandardJavaFilemanager 1、初始化JavaCompiler: JavaCompiler compiler = ToolProvider.getSystemJavaCompiler
Groovy 提供的 GroovyClassLoader 来将 Java 字符串解析成 Java Class,然后通过反射的方法的得到对应的 Java 对象 使用 Java 提供的 javax.tools.JavaCompiler (Exception e) { return groovyClassLoader.parseClass(codeSource); } } } 使用 javax.tools.JavaCompiler 来编译代码 javax.tools.JavaCompiler 的使用相对麻烦些,以下代码不保证在不同的 jdk 中可以正常使用 package org.example.dyscript.compiler ; import javax.tools.JavaCompiler; import javax.tools.JavaCompiler.CompilationTask; import javax.tools.JavaFileObject 为了解决损失的那一点性能提供两种将 Java 代码直接转成对 Java 对象的方法,使用这种方式性能于直接使用 Java 硬编码相同 使用 Groovy 来编译代码更加安全可靠,javax.tools.JavaCompiler
废话不多说,直接上代码: package com.luban.proxy; import com.sun.jndi.toolkit.url.UrlUtil; import javax.tools.JavaCompiler fw.write(content); fw.flush(); fw.close(); //编译.java文件 JavaCompiler 是java的动态编译类 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); //使用动态编译创建文件管理器 Iterable units = fileMgr.getJavaFileObjects(file); //添加编译文件的任务 JavaCompiler.CompilationTask Exception e){ e.printStackTrace(); } return proxy; } } 综上代码中比较难理解的是动态编译类JavaCompiler
javaCompiler = ToolProvider.getSystemJavaCompiler(); // 标注java文件管理器,用来获取java字节码文件 StandardJavaFileManager manager = javaCompiler.getStandardFileManager(null,null,null); Iterable task = javaCompiler.getTask(null,manager,null,null,null,iterable); // 开始执行task javaCompiler = ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager manager = javaCompiler.getStandardFileManager task = javaCompiler.getTask(null,manager,null,null,null,iterable); task.call();
args) { String path1 = "/path/to/LamdbaTest1.java"; String path2 = "/path/to/LamdbaTest2.java"; JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler(); DiagnosticCollector diagnostics = new DiagnosticCollector (); StandardJavaFileManager fileManager = javaCompiler.getStandardFileManager(diagnostics, null, null compilationUnits = fileManager.getJavaFileObjects( new File(path1), new File(path2) ); JavaCompiler.CompilationTask task = javaCompiler.getTask(null, fileManager, diagnostics, null, null, compilationUnits); boolean
Runtime run = Runtime.getRuntime(); Process process = run.exec("javac -cp d:/myjava/ HelloWorld.java"); 通过JavaCompiler 动态编译 通过JavaCompiler动态编译 ?
com.sun.tools.javac.processing.JavacProcessingEnvironment.doProcessing(JavacProcessingEnvironment.java:1311) at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.processAnnotations (JavaCompiler.java:1250) at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java
return rt.invoke(clazz.newInstance()); } }*/ import java.util.Arrays; import javax.tools.JavaCompiler.CompilationTask ; import javax.tools.SimpleJavaFileObject; import javax.tools.JavaFileObject; import javax.tools.JavaCompiler > findClass(String str) throws ClassNotFoundException { JavaCompiler compiler = ToolProvider.getSystemJavaCompiler + "bin"; Iterable<String> stringdir = Arrays.asList(flag, outDir); // 指定-d dir 参数 // 建立一个编译任务 JavaCompiler.CompilationTask
> compileToClass(String fullClassName, String javaCode) throws Exception { JavaCompiler compiler options.add("UTF-8"); options.add("-classpath"); options.add(this.classpath); JavaCompiler.CompilationTask org.apache.log4j.Logger; import sun.misc.ClassLoaderUtil; import javax.tools.DiagnosticCollector; import javax.tools.JavaCompiler null; URLClassLoader urlClassLoader = null; try { //获取系统编译器 JavaCompiler //设定使用javaUtilZip,避免zipFileIndex泄漏 options.add("-XDuseJavaUtilZip"); JavaCompiler.CompilationTask
结果当然是suer,在JDK6及以上中已经支持了java代码动态编译(JavaCompiler) Java的动态编译对源提供了多个渠道。 SimpleJavaFileObject、ForwardingJavaFileObject public void compileClass(String name, String code) { private final JavaCompiler protected final Map<String, Output> map = new HashMap<String, Output>(); public FileManager(JavaCompiler