猿问
下载APP

使用javax.tools.JavaCompiler在内存中完全编译代码

我正在使用javax.tools包(JDK 1.7)中的JavaCompiler即时编译一些内容,如下所示:


compiler.run(null, null, "-cp", paths, "path/to/my/file.java");

它可以工作,但我想在内存中完成所有操作(例如,传递带有代码的字符串,而不是源文件,并返回字节码而不是.class文件)。我发现扩展InputStream和OutputStream参数没有用,因为它可能与控制台中的相同。您知道一种使run方法像这样工作的方法吗?还是您知道使用该getTask()方法执行此操作的可靠方法?(扩展FileManager看起来很容易,但并不容易:)


慕侠2389804
浏览 80回答 3
3回答

RISEBY

我已经在Mac OS Java 7中运行了上面的代码。它们都不起作用。所以我写了一个 https://github.com/trung/InMemoryJavaCompilerStringBuffer sourceCode = new StringBuffer();sourceCode.append("package org.mdkt;\n");sourceCode.append("public class HelloClass {\n");sourceCode.append("&nbsp; &nbsp;public String hello() { return \"hello\"; }");sourceCode.append("}");Class<?> helloClass = InMemoryJavaCompiler.compile("org.mdkt.HelloClass", sourceCode.toString());

BIG阳

我认为这可能会有所帮助,它基本上说明了如何从内存中编译Java源代码(该字符串位于类中)。它使用PrinterWriter和StringWriter将源代码写入String/ in内存,然后使用JavaCompiler该类(自JDK 6起)来编译和运行程序:import javax.tools.Diagnostic;import javax.tools.DiagnosticCollector;import javax.tools.JavaCompiler;import javax.tools.JavaCompiler.CompilationTask;import javax.tools.JavaFileObject;import javax.tools.SimpleJavaFileObject;import javax.tools.ToolProvider;import java.io.File;import java.io.IOException;import java.io.PrintWriter;import java.io.StringWriter;import java.lang.reflect.InvocationTargetException;import java.net.URI;import java.net.URL;import java.net.URLClassLoader;import java.util.Arrays;public class CompileSourceInMemory {&nbsp; public static void main(String args[]) throws IOException {&nbsp; &nbsp; JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();&nbsp; &nbsp; DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();&nbsp; &nbsp; StringWriter writer = new StringWriter();&nbsp; &nbsp; PrintWriter out = new PrintWriter(writer);&nbsp; &nbsp; out.println("public class HelloWorld {");&nbsp; &nbsp; out.println("&nbsp; public static void main(String args[]) {");&nbsp; &nbsp; out.println("&nbsp; &nbsp; System.out.println(\"This is in another java file\");");&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; out.println("&nbsp; }");&nbsp; &nbsp; out.println("}");&nbsp; &nbsp; out.close();&nbsp; &nbsp; JavaFileObject file = new JavaSourceFromString("HelloWorld", writer.toString());&nbsp; &nbsp; Iterable<? extends JavaFileObject> compilationUnits = Arrays.asList(file);&nbsp; &nbsp; CompilationTask task = compiler.getTask(null, null, diagnostics, null, null, compilationUnits);&nbsp; &nbsp; boolean success = task.call();&nbsp; &nbsp; for (Diagnostic diagnostic : diagnostics.getDiagnostics()) {&nbsp; &nbsp; &nbsp; System.out.println(diagnostic.getCode());&nbsp; &nbsp; &nbsp; System.out.println(diagnostic.getKind());&nbsp; &nbsp; &nbsp; System.out.println(diagnostic.getPosition());&nbsp; &nbsp; &nbsp; System.out.println(diagnostic.getStartPosition());&nbsp; &nbsp; &nbsp; System.out.println(diagnostic.getEndPosition());&nbsp; &nbsp; &nbsp; System.out.println(diagnostic.getSource());&nbsp; &nbsp; &nbsp; System.out.println(diagnostic.getMessage(null));&nbsp; &nbsp; }&nbsp; &nbsp; System.out.println("Success: " + success);&nbsp; &nbsp; if (success) {&nbsp; &nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; URLClassLoader classLoader = URLClassLoader.newInstance(new URL[] { new File("").toURI().toURL() });&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Class.forName("HelloWorld", true, classLoader).getDeclaredMethod("main", new Class[] { String[].class }).invoke(null, new Object[] { null });&nbsp; &nbsp; &nbsp; } catch (ClassNotFoundException e) {&nbsp; &nbsp; &nbsp; &nbsp; System.err.println("Class not found: " + e);&nbsp; &nbsp; &nbsp; } catch (NoSuchMethodException e) {&nbsp; &nbsp; &nbsp; &nbsp; System.err.println("No such method: " + e);&nbsp; &nbsp; &nbsp; } catch (IllegalAccessException e) {&nbsp; &nbsp; &nbsp; &nbsp; System.err.println("Illegal access: " + e);&nbsp; &nbsp; &nbsp; } catch (InvocationTargetException e) {&nbsp; &nbsp; &nbsp; &nbsp; System.err.println("Invocation target: " + e);&nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; }}class JavaSourceFromString extends SimpleJavaFileObject {&nbsp; final String code;&nbsp; JavaSourceFromString(String name, String code) {&nbsp; &nbsp; super(URI.create("string:///" + name.replace('.','/') + Kind.SOURCE.extension),Kind.SOURCE);&nbsp; &nbsp; this.code = code;&nbsp; }&nbsp; @Override&nbsp; public CharSequence getCharContent(boolean ignoreEncodingErrors) {&nbsp; &nbsp; return code;&nbsp; }}如果您查看参考链接,也会发现其他一些示例

噜噜哒

这是一个完全在内存中编译的类。我已经(几乎)从Rekha Kumari(2011年6月)的http://javapracs.blogspot.de/2011/06/dynamic-in-memory-compilation-using.html中获取了全部内容。尽管此版本短了一百多行,并具有更多功能(但没有docs:P)。它可以一次编译多个类,这是编译相互依赖的类的唯一方法。如果您对类“ CompilerFeedback”感到疑惑:我正在开发一个小型Java IDE,用于需要该代码的游戏。我将其包含在此处是因为我假设您想使用此编译器进行某些操作,而这种简化可能会有所帮助。(我意识到CompilerFeedback类中的某些代码是完全废话。它是经过一年的尝试而被回收的。还有一个实用程序方法,不需要编译,可以从类的源代码(包括包名,如果提供)中得到完整的类名。对于调用此信息的编译器非常有用。演示班:import java.util.ArrayList;import java.util.List;public class Demo {&nbsp; &nbsp; public static void main(final String[] args) {&nbsp; &nbsp; &nbsp; &nbsp; final InMemoryCompiler.IMCSourceCode cls1source;&nbsp; &nbsp; &nbsp; &nbsp; final InMemoryCompiler.IMCSourceCode cls2source;&nbsp; &nbsp; &nbsp; &nbsp; final StringBuilder sb = new StringBuilder();&nbsp; &nbsp; &nbsp; &nbsp; sb.append("package toast;\n");&nbsp; &nbsp; &nbsp; &nbsp; sb.append("public class DynaClass {\n");&nbsp; &nbsp; &nbsp; &nbsp; sb.append("&nbsp; &nbsp; public static void main(final String[] args) {");&nbsp; &nbsp; &nbsp; &nbsp; sb.append("&nbsp; &nbsp; &nbsp; &nbsp; System.out.println(\"Based massively on the work of Rekha Kumari, http://javapracs.blogspot.de/2011/06/dynamic-in-memory-compilation-using.html\");\n");&nbsp; &nbsp; &nbsp; &nbsp; sb.append("&nbsp; &nbsp; &nbsp; &nbsp; System.out.println(\"This is the main method speaking.\");\n");&nbsp; &nbsp; &nbsp; &nbsp; sb.append("&nbsp; &nbsp; &nbsp; &nbsp; System.out.println(\"Args: \" + java.util.Arrays.toString(args));\n");&nbsp; &nbsp; &nbsp; &nbsp; sb.append("&nbsp; &nbsp; &nbsp; &nbsp; final Test test = new Test();\n");&nbsp; &nbsp; &nbsp; &nbsp; sb.append("&nbsp; &nbsp; }\n");&nbsp; &nbsp; &nbsp; &nbsp; sb.append("&nbsp; &nbsp; public String toString() {\n");&nbsp; &nbsp; &nbsp; &nbsp; sb.append("&nbsp; &nbsp; &nbsp; &nbsp; return \"Hello, I am \" + ");&nbsp; &nbsp; &nbsp; &nbsp; sb.append("this.getClass().getSimpleName();\n");&nbsp; &nbsp; &nbsp; &nbsp; sb.append("&nbsp; &nbsp; }\n");&nbsp; &nbsp; &nbsp; &nbsp; sb.append("}\n");&nbsp; &nbsp; &nbsp; &nbsp; cls1source = new InMemoryCompiler.IMCSourceCode("toast.DynaClass", sb.toString());&nbsp; &nbsp; &nbsp; &nbsp; sb.setLength(0);&nbsp; &nbsp; &nbsp; &nbsp; sb.append("package toast;\n");&nbsp; &nbsp; &nbsp; &nbsp; sb.append("public class Test {\n");&nbsp; &nbsp; &nbsp; &nbsp; sb.append("&nbsp; &nbsp; public Test() {\n");&nbsp; &nbsp; &nbsp; &nbsp; sb.append("&nbsp; &nbsp; &nbsp; &nbsp; System.out.println(\"class Test constructor reporting in.\");\n");&nbsp; &nbsp; &nbsp; &nbsp; sb.append("&nbsp; &nbsp; &nbsp; &nbsp; System.out.println(new DynaClass());\n");&nbsp; &nbsp; &nbsp; &nbsp; sb.append("&nbsp; &nbsp; }\n");&nbsp; &nbsp; &nbsp; &nbsp; sb.append("}\n");&nbsp; &nbsp; &nbsp; &nbsp; cls2source = new InMemoryCompiler.IMCSourceCode("toast.Test", sb.toString());&nbsp; &nbsp; &nbsp; &nbsp; final List<InMemoryCompiler.IMCSourceCode> classSources = new ArrayList<>();&nbsp; &nbsp; &nbsp; &nbsp; classSources.add(cls1source);&nbsp; &nbsp; &nbsp; &nbsp; classSources.add(cls2source);&nbsp; &nbsp; &nbsp; &nbsp; final InMemoryCompiler uCompiler = new InMemoryCompiler(classSources);&nbsp; &nbsp; &nbsp; &nbsp; final CompilerFeedback compilerFeedback = uCompiler.compile();&nbsp; &nbsp; &nbsp; &nbsp; System.out.println("\n\nCOMPILER FEEDBACK: " + compilerFeedback);&nbsp; &nbsp; &nbsp; &nbsp; if (compilerFeedback != null && compilerFeedback.success) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; System.out.println("\nTOSTRING DEMO:");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; uCompiler.runToString(cls1source.fullClassName);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } catch (Exception e) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e.printStackTrace();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; System.out.println("\nMAIN DEMO:");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; uCompiler.runMain(cls1source.fullClassName, new String[] { "test1", "test2" });&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } catch (Exception e) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e.printStackTrace();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; System.exit(0);&nbsp; &nbsp; }}编译器类:import javax.tools.*;import java.io.ByteArrayOutputStream;import java.io.IOException;import java.io.OutputStream;import java.lang.reflect.InvocationTargetException;import java.lang.reflect.Method;import java.net.URI;import java.security.SecureClassLoader;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;/**&nbsp;* MASSIVELY based on http://javapracs.blogspot.de/2011/06/dynamic-in-memory-compilation-using.html by Rekha Kumari&nbsp;* (June 2011)&nbsp;*/final public class InMemoryCompiler {&nbsp; &nbsp; final public static class IMCSourceCode {&nbsp; &nbsp; &nbsp; &nbsp; final public String fullClassName;&nbsp; &nbsp; &nbsp; &nbsp; final public String sourceCode;&nbsp; &nbsp; &nbsp; &nbsp; /**&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* @param fullClassName Full name of the class that will be compiled. If the class should be in some package,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fullName should contain it too, for example: "testpackage.DynaClass"&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;* @param sourceCode&nbsp; &nbsp; the source code&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;*/&nbsp; &nbsp; &nbsp; &nbsp; public IMCSourceCode(final String fullClassName, final String sourceCode) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.fullClassName = fullClassName;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.sourceCode = sourceCode;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; final public boolean valid;&nbsp; &nbsp; final private List<IMCSourceCode> classSourceCodes;&nbsp; &nbsp; final private JavaFileManager fileManager;&nbsp; &nbsp; public InMemoryCompiler(final List<IMCSourceCode> classSourceCodes) {&nbsp; &nbsp; &nbsp; &nbsp; this.classSourceCodes = classSourceCodes;&nbsp; &nbsp; &nbsp; &nbsp; final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();&nbsp; &nbsp; &nbsp; &nbsp; if (compiler == null) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fileManager = null;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; valid = false;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; System.err.println("ToolProvider.getSystemJavaCompiler() returned null! This program needs to be run on a system with an installed JDK.");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; valid = true;&nbsp; &nbsp; &nbsp; &nbsp; fileManager = new ForwardingJavaFileManager<JavaFileManager>(compiler.getStandardFileManager(null, null, null)) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; final private Map<String, ByteArrayOutputStream> byteStreams = new HashMap<>();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @Override&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; public ClassLoader getClassLoader(final Location location) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return new SecureClassLoader() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @Override&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; protected Class<?> findClass(final String className) throws ClassNotFoundException {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; final ByteArrayOutputStream bos = byteStreams.get(className);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (bos == null) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return null;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; final byte[] b = bos.toByteArray();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return super.defineClass(className, b, 0, b.length);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; };&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @Override&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; public JavaFileObject getJavaFileForOutput(final Location location, final String className, final JavaFileObject.Kind kind, final FileObject sibling) throws IOException {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return new SimpleJavaFileObject(URI.create("string:///" + className.replace('.', '/') + kind.extension), kind) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @Override&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; public OutputStream openOutputStream() throws IOException {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ByteArrayOutputStream bos = byteStreams.get(className);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (bos == null) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bos = new ByteArrayOutputStream();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; byteStreams.put(className, bos);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return bos;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; };&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; };&nbsp; &nbsp; }&nbsp; &nbsp; public CompilerFeedback compile() {&nbsp; &nbsp; &nbsp; &nbsp; if (!valid) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return null;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; final List<JavaFileObject> files = new ArrayList<>();&nbsp; &nbsp; &nbsp; &nbsp; for (IMCSourceCode classSourceCode : classSourceCodes) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; URI uri = null;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; uri = URI.create("string:///" + classSourceCode.fullClassName.replace('.', '/') + JavaFileObject.Kind.SOURCE.extension);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } catch (Exception e) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e.printStackTrace();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (uri != null) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; final SimpleJavaFileObject sjfo = new SimpleJavaFileObject(uri, JavaFileObject.Kind.SOURCE) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @Override&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; public CharSequence getCharContent(final boolean ignoreEncodingErrors) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return classSourceCode.sourceCode;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; };&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; files.add(sjfo);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; final DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();&nbsp; &nbsp; &nbsp; &nbsp; final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();&nbsp; &nbsp; &nbsp; &nbsp; if (files.size() > 0) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; final JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnostics, null, null, files);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return new CompilerFeedback(task.call(), diagnostics);&nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return null;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; public void runToString(final String className) throws InstantiationException, IllegalAccessException, ClassNotFoundException {&nbsp; &nbsp; &nbsp; &nbsp; if (!valid) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; final Class<?> theClass = getCompiledClass(className);&nbsp; &nbsp; &nbsp; &nbsp; final Object instance = theClass.newInstance();&nbsp; &nbsp; &nbsp; &nbsp; System.out.println(instance);&nbsp; &nbsp; }&nbsp; &nbsp; public void runMain(final String className, final String[] args) throws IllegalAccessException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException {&nbsp; &nbsp; &nbsp; &nbsp; if (!valid) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; final Class<?> theClass = getCompiledClass(className);&nbsp; &nbsp; &nbsp; &nbsp; final Method mainMethod = theClass.getDeclaredMethod("main", String[].class);&nbsp; &nbsp; &nbsp; &nbsp; mainMethod.invoke(null, new Object[] { args });&nbsp; &nbsp; }&nbsp; &nbsp; public Class<?> getCompiledClass(final String className) throws ClassNotFoundException {&nbsp; &nbsp; &nbsp; &nbsp; if (!valid) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw new IllegalStateException("InMemoryCompiler instance not usable because ToolProvider.getSystemJavaCompiler() returned null: No JDK installed.");&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; final ClassLoader classLoader = fileManager.getClassLoader(null);&nbsp; &nbsp; &nbsp; &nbsp; final Class<?> ret = classLoader.loadClass(className);&nbsp; &nbsp; &nbsp; &nbsp; if (ret == null) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw new ClassNotFoundException("Class returned by ClassLoader was null!");&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return ret;&nbsp; &nbsp; }}电脑反馈类:import javax.tools.Diagnostic;import javax.tools.DiagnosticCollector;import javax.tools.JavaFileObject;import javax.tools.SimpleJavaFileObject;import java.io.IOException;import java.util.ArrayList;import java.util.List;import java.util.Locale;final public class CompilerFeedback {&nbsp; &nbsp; final public boolean success;&nbsp; &nbsp; final public List<CompilerMessage> messages = new ArrayList<>();&nbsp; &nbsp; public CompilerFeedback(final Boolean success, final DiagnosticCollector<JavaFileObject> diagnostics) {&nbsp; &nbsp; &nbsp; &nbsp; this.success = success != null && success;&nbsp; &nbsp; &nbsp; &nbsp; for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; messages.add(new CompilerMessage(diagnostic));&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; public String toString() {&nbsp; &nbsp; &nbsp; &nbsp; final StringBuilder sb = new StringBuilder();&nbsp; &nbsp; &nbsp; &nbsp; sb.append("SUCCESS: ").append(success).append('\n');&nbsp; &nbsp; &nbsp; &nbsp; final int iTop = messages.size();&nbsp; &nbsp; &nbsp; &nbsp; for (int i = 0; i < iTop; i++) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sb.append("\n[MESSAGE ").append(i + 1).append(" OF ").append(iTop).append("]\n\n");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // sb.append(messages.get(i).toString()).append("\n");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // sb.append(messages.get(i).toStringForList()).append("\n");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sb.append(messages.get(i).toStringForDebugging()).append("\n");&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return sb.toString();&nbsp; &nbsp; }&nbsp; &nbsp; final public static class CompilerMessage {&nbsp; &nbsp; &nbsp; &nbsp; final public Diagnostic<? extends JavaFileObject> compilerInfo;&nbsp; &nbsp; &nbsp; &nbsp; final public String typeOfProblem;&nbsp; &nbsp; &nbsp; &nbsp; final public String typeOfProblem_forDebugging;&nbsp; &nbsp; &nbsp; &nbsp; final public String multiLineMessage;&nbsp; &nbsp; &nbsp; &nbsp; final public int lineNumber;&nbsp; &nbsp; &nbsp; &nbsp; final public int columnNumber;&nbsp; &nbsp; &nbsp; &nbsp; final public int textHighlightPos_lineStart;&nbsp; &nbsp; &nbsp; &nbsp; final public int textHighlightPos_problemStart;&nbsp; &nbsp; &nbsp; &nbsp; final public int textHighlightPos_problemEnd;&nbsp; &nbsp; &nbsp; &nbsp; final public String sourceCode;&nbsp; &nbsp; &nbsp; &nbsp; final public String codeOfConcern;&nbsp; &nbsp; &nbsp; &nbsp; final public String codeOfConcernLong;&nbsp; &nbsp; &nbsp; &nbsp; CompilerMessage(final Diagnostic<? extends JavaFileObject> diagnostic) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; final JavaFileObject sourceFileObject = diagnostic.getSource();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; String sourceCodePreliminary = null;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (sourceFileObject instanceof SimpleJavaFileObject) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; final SimpleJavaFileObject simpleSourceFileObject = (SimpleJavaFileObject) sourceFileObject;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; try {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; final CharSequence charSequence = simpleSourceFileObject.getCharContent(false);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sourceCodePreliminary = charSequence.toString();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } catch (IOException e) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; e.printStackTrace();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (sourceCodePreliminary == null) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sourceCode = "[SOURCE CODE UNAVAILABLE]";&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sourceCode = sourceCodePreliminary;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; compilerInfo = diagnostic;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; typeOfProblem = diagnostic.getKind().name();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; typeOfProblem_forDebugging = "toString() = " + diagnostic.getKind().toString() + "; name() = " + typeOfProblem;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lineNumber = (int) compilerInfo.getLineNumber();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; columnNumber = (int) compilerInfo.getColumnNumber();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; final int sourceLen = sourceCode.length();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; textHighlightPos_lineStart = (int) Math.min(Math.max(0, diagnostic.getStartPosition()), sourceLen);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; textHighlightPos_problemStart = (int) Math.min(Math.max(0, diagnostic.getPosition()), sourceLen);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; textHighlightPos_problemEnd = (int) Math.min(Math.max(0, diagnostic.getEndPosition()), sourceLen);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; final StringBuilder reformattedMessage = new StringBuilder();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; final String message = diagnostic.getMessage(Locale.US);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; final int messageCutOffPosition = message.indexOf("location:");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; final String[] messageParts;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (messageCutOffPosition >= 0) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; messageParts = message.substring(0, messageCutOffPosition).split("\n");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; messageParts = message.split("\n");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (String s : messageParts) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; String s2 = s.trim();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (s2.length() > 0) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; boolean lengthChanged;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; do {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; final int lBeforeReplace = s2.length();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; s2 = s2.replace("&nbsp; ", " ");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; lengthChanged = (s2.length() != lBeforeReplace);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } while (lengthChanged);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; reformattedMessage.append(s2).append("\n");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; codeOfConcern = sourceCode.substring(textHighlightPos_problemStart, textHighlightPos_problemEnd);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; codeOfConcernLong = sourceCode.substring(textHighlightPos_lineStart, textHighlightPos_problemEnd);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!codeOfConcern.isEmpty()) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; reformattedMessage.append("Code of concern: \"").append(codeOfConcern).append('\"');&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; multiLineMessage = reformattedMessage.toString();&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; public String toStringForList() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (compilerInfo == null) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return "No compiler!";&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return compilerInfo.getCode();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; public String toStringForDebugging() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; final StringBuilder ret = new StringBuilder();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ret.append("Type of problem: ").append(typeOfProblem_forDebugging).append("\n\n");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ret.append("Message:\n").append(multiLineMessage).append("\n\n");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ret.append(compilerInfo.getCode()).append("\n\n");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ret.append("line number: ").append(lineNumber).append("\n");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ret.append("column number: ").append(columnNumber).append("\n");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ret.append("textHighlightPos_lineStart: ").append(textHighlightPos_lineStart).append("\n");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ret.append("textHighlightPos_problemStart: ").append(textHighlightPos_problemStart).append("\n");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ret.append("textHighlightPos_problemEnd: ").append(textHighlightPos_problemEnd).append("\n");&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return ret.toString();&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; @Override&nbsp; &nbsp; &nbsp; &nbsp; public String toString() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; //&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return compilerInfo.getMessage(Locale.US);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return typeOfProblem + ": " + multiLineMessage + "\n";&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}实用方法(以后的三堂课都不需要。):final public static String PREFIX_CLASSNAME = "class ";final public static String PREFIX_PACKAGENAME = "package ";final public static String CHARSET_JAVAKEYWORDENDERS = " \n[](){}<>;,\"\\/*+-=%!&?@:";/**&nbsp;* @return e.g. "com.dreamspacepresident.TestClass" if the source's first root level "class" (I'm talking about {}&nbsp;* hierarchy.) is named "TestClass", and if the "package" name is "com.dreamspacepresident". Null is returned if&nbsp;* sourceCode is null or does not provide a class name. (Mind that the parsing is done in a quite crappy way.)&nbsp;*/public static String deriveFullClassNameFromSource(final String sourceCode) {&nbsp; &nbsp; if (sourceCode == null) {&nbsp; &nbsp; &nbsp; &nbsp; return null;&nbsp; &nbsp; }&nbsp; &nbsp; final int firstBr = sourceCode.indexOf('{');&nbsp; &nbsp; if (firstBr >= 0) {&nbsp; &nbsp; &nbsp; &nbsp; // DETERMINE CLASS NAME&nbsp; &nbsp; &nbsp; &nbsp; final int firstClass = sourceCode.indexOf(PREFIX_CLASSNAME);&nbsp; &nbsp; &nbsp; &nbsp; if (firstClass < firstBr) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; String className = sourceCode.substring(firstClass + PREFIX_CLASSNAME.length(), firstBr).trim();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; final int classNameEnd = indexOfAnyOfThese(className, CHARSET_JAVAKEYWORDENDERS);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (classNameEnd >= 0) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; className = className.substring(0, classNameEnd);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!className.isEmpty()) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // DETERMINE PACKAGE NAME&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; String packageName = null;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; final int firstPackage = sourceCode.indexOf(PREFIX_PACKAGENAME);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (firstPackage >= 0 && firstPackage < firstBr && firstPackage < firstClass) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; packageName = sourceCode.substring(firstPackage + PREFIX_PACKAGENAME.length(), firstBr).trim();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; final int packageNameEnd = indexOfAnyOfThese(packageName, CHARSET_JAVAKEYWORDENDERS);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (packageNameEnd >= 0) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; packageName = packageName.substring(0, packageNameEnd);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return (packageName != null && !packageName.isEmpty() ? packageName + "." : "") + className;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; return null;}/**&nbsp;* Looks for the first occurrence of ANY of the given characters, which is easier than using a bunch of&nbsp;* String.indexOf() calls.&nbsp;*&nbsp;* @return -1 if not found, otherwise the String index of the first hit&nbsp;*/public static int indexOfAnyOfThese(final String text, final String characters) {&nbsp; &nbsp; if (text != null && !text.isEmpty() && characters != null && !characters.isEmpty()) {&nbsp; &nbsp; &nbsp; &nbsp; final int lenT = text.length();&nbsp; &nbsp; &nbsp; &nbsp; final int lenC = characters.length();&nbsp; &nbsp; &nbsp; &nbsp; for (int i = 0; i < lenT; i++) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; final char c = text.charAt(i);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (int ii = 0; ii < lenC; ii++) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (c == characters.charAt(ii)) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return i;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; return -1;}
打开App,查看更多内容
随时随地看视频慕课网APP
我要回答