1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
|
@Slf4j @Component @Scope("singleton") public final class CompilerPool {
private final static int COMPILER_POOL_SIZE = Runtime.getRuntime().availableProcessors(); private final static ConcurrentLinkedQueue<TensorJavaCompiler> COMPILER_POOL = new ConcurrentLinkedQueue<>(); private final static ClassLoader parentClassloader = CompilerPool.class.getClassLoader();
static { for (int i = 0; i < COMPILER_POOL_SIZE; i ++) { COMPILER_POOL.add(new TensorJavaCompiler()); } }
public CompilerResult work(String javaName, String javaSourceCode) { TensorJavaCompiler compiler = COMPILER_POOL.poll(); if (compiler == null) { return new CompilerResult(); } return compiler.buildTask(javaName, javaSourceCode).compile(new CompilerResult()); }
private final static class TensorJavaCompiler {
private volatile boolean isRunning; private JavaCompiler compiler; private DiagnosticCollector<JavaFileObject> diagnostics; private String javaName; private JavaCompiler.CompilationTask task; private TensorClassLoader classLoader; private String classpath; private ClassFileManager fileManager;
private TensorJavaCompiler() { isRunning = false; compiler = ToolProvider.getSystemJavaCompiler(); diagnostics = new DiagnosticCollector<>(); classLoader = new TensorClassLoader(parentClassloader); fileManager = new ClassFileManager(compiler.getStandardFileManager(diagnostics, null, null)); buildClassPath(); }
void buildClassPath() { this.classpath = null; StringBuilder sb = new StringBuilder(); for (URL url : this.classLoader.getURLs()) { String p = url.getFile(); sb.append(p).append(File.pathSeparator); } this.classpath = sb.toString(); }
TensorJavaCompiler buildTask(String name, String source) { javaName = name; List<JavaFileObject> fileObjects = new ArrayList<>(); fileObjects.add(new JavaSourceObject(javaName, source)); List<String> options = new ArrayList<>(); options.add("-encoding"); options.add("UTF-8"); options.add("-classpath"); options.add(this.classpath); task = compiler.getTask(null, fileManager, diagnostics, options, null, fileObjects); return this; }
CompilerResult compile(CompilerResult result) { isRunning = true; String compilerErr = ""; if (task.call()) { try { PrintStream old = System.out; ByteArrayOutputStream bos = new ByteArrayOutputStream(1024); PrintStream print = new PrintStream(bos); System.setOut(print); JavaClassObject classObject = fileManager.getJavaClassObject(); Class cls = classLoader.loadClass(javaName, classObject); result.setResult(cls.getDeclaredMethod("main", String[].class).invoke(null, new Object[]{null})); System.setOut(old); result.setPrintMsg(bos.toString()); } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { log.error("compiler exception is ", e); } } else { String compilerErr = ""; for (Diagnostic diagnostic : diagnostics.getDiagnostics()) { compilerErr += compilePrint(diagnostic); } result.setCompilerErr(compilerErr); } result.setTimeout(false); release(); return result; }
public boolean isRunning() { return isRunning; }
private void release() { isRunning = false; COMPILER_POOL.add(this); }
private String compilePrint(Diagnostic diagnostic) { StringBuffer res = new StringBuffer(); res.append("Code:[").append(diagnostic.getCode()).append("]\n"); res.append("Kind:[").append(diagnostic.getKind()).append("]\n"); res.append("Position:[").append(diagnostic.getPosition()).append("]\n"); res.append("Start Position:[").append(diagnostic.getStartPosition()).append("]\n"); res.append("End Position:[").append(diagnostic.getEndPosition()).append("]\n"); res.append("Source:[").append(diagnostic.getSource()).append("]\n"); res.append("Message:[").append(diagnostic.getMessage(null)).append("]\n"); res.append("LineNumber:[").append(diagnostic.getLineNumber()).append("]\n"); res.append("ColumnNumber:[").append(diagnostic.getColumnNumber()).append("]\n"); return res.toString(); } } }
|