JdkCompiler는 code를 통해 동적으로 컴파일됨
13133 단어 compiler
쓰다
대응하는 원본 코드를class 대상으로 컴파일하여load로 시스템에 들어갑니다
를 참고하십시오.그리고 두보에 비슷한 코드가 있다고 생각하고 파렴치한 코피를 해요.대응하는 코드는 다음과 같다.
package com.taobao.ju.hsfer.util;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.tools.DiagnosticCollector;
import javax.tools.FileObject;
import javax.tools.ForwardingJavaFileManager;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.StandardLocation;
import javax.tools.ToolProvider;
public class JdkCompiler {
private final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
private final DiagnosticCollector<JavaFileObject> diagnosticCollector = new DiagnosticCollector<JavaFileObject>();
private final ClassLoaderImpl classLoader;
private final JavaFileManagerImpl javaFileManager;
private volatile List<String> options;
public JdkCompiler(){
options = new ArrayList<String>();
options.add("-target");
options.add("1.6");
StandardJavaFileManager manager = compiler.getStandardFileManager(diagnosticCollector, null, null);
final ClassLoader loader = Thread.currentThread().getContextClassLoader();
if (loader instanceof URLClassLoader
&& (! loader.getClass().getName().equals("sun.misc.Launcher$AppClassLoader"))) {
try {
URLClassLoader urlClassLoader = (URLClassLoader) loader;
List<File> files = new ArrayList<File>();
for (URL url : urlClassLoader.getURLs()) {
files.add(new File(url.getFile()));
}
manager.setLocation(StandardLocation.CLASS_PATH, files);
} catch (IOException e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
classLoader = AccessController.doPrivileged(new PrivilegedAction<ClassLoaderImpl>() {
public ClassLoaderImpl run() {
return new ClassLoaderImpl(loader);
}
});
javaFileManager = new JavaFileManagerImpl(manager, classLoader);
}
public Class<?> doCompile(String name, String sourceCode) throws Throwable {
int i = name.lastIndexOf('.');
String packageName = i < 0 ? "" : name.substring(0, i);
String className = i < 0 ? name : name.substring(i + 1);
JavaFileObjectImpl javaFileObject = new JavaFileObjectImpl(className, sourceCode);
javaFileManager.putFileForInput(StandardLocation.SOURCE_PATH, packageName,
className + ClassUtils.JAVA_EXTENSION, javaFileObject);
Boolean result = compiler.getTask(null, javaFileManager, diagnosticCollector, options,
null, Arrays.asList(javaFileObject)).call();
if (result == null || !result) {
throw new IllegalStateException("Compilation failed. class: " + name + ", diagnostics: " + diagnosticCollector);
}
return classLoader.loadClass(name);
}
private final class ClassLoaderImpl extends ClassLoader {
private final Map<String, JavaFileObject> classes = new HashMap<String, JavaFileObject>();
ClassLoaderImpl(final ClassLoader parentClassLoader) {
super(parentClassLoader);
}
Collection<JavaFileObject> files() {
return Collections.unmodifiableCollection(classes.values());
}
@Override
protected Class<?> findClass(final String qualifiedClassName) throws ClassNotFoundException {
JavaFileObject file = classes.get(qualifiedClassName);
if (file != null) {
byte[] bytes = ((JavaFileObjectImpl) file).getByteCode();
return defineClass(qualifiedClassName, bytes, 0, bytes.length);
}
try {
return Thread.currentThread().getContextClassLoader().loadClass(qualifiedClassName);
// return ClassHelper.forNameWithCallerClassLoader(qualifiedClassName, getClass());
} catch (ClassNotFoundException nf) {
return super.findClass(qualifiedClassName);
}
}
void add(final String qualifiedClassName, final JavaFileObject javaFile) {
classes.put(qualifiedClassName, javaFile);
}
@Override
protected synchronized Class<?> loadClass(final String name, final boolean resolve) throws ClassNotFoundException {
return super.loadClass(name, resolve);
}
@Override
public InputStream getResourceAsStream(final String name) {
if (name.endsWith(ClassUtils.CLASS_EXTENSION)) {
String qualifiedClassName = name.substring(0, name.length() - ClassUtils.CLASS_EXTENSION.length()).replace('/', '.');
JavaFileObjectImpl file = (JavaFileObjectImpl) classes.get(qualifiedClassName);
if (file != null) {
return new ByteArrayInputStream(file.getByteCode());
}
}
return super.getResourceAsStream(name);
}
}
private static final class JavaFileObjectImpl extends SimpleJavaFileObject {
private ByteArrayOutputStream bytecode;
private final CharSequence source;
public JavaFileObjectImpl(final String baseName, final CharSequence source){
super(ClassUtils.toURI(baseName + ClassUtils.JAVA_EXTENSION), Kind.SOURCE);
this.source = source;
}
JavaFileObjectImpl(final String name, final Kind kind){
super(ClassUtils.toURI(name), kind);
source = null;
}
@Override
public CharSequence getCharContent(final boolean ignoreEncodingErrors) throws UnsupportedOperationException {
if (source == null) {
throw new UnsupportedOperationException("source == null");
}
return source;
}
@Override
public InputStream openInputStream() {
return new ByteArrayInputStream(getByteCode());
}
@Override
public OutputStream openOutputStream() {
return bytecode = new ByteArrayOutputStream();
}
public byte[] getByteCode() {
return bytecode.toByteArray();
}
}
private static final class JavaFileManagerImpl extends ForwardingJavaFileManager<JavaFileManager> {
private final ClassLoaderImpl classLoader;
private final Map<URI, JavaFileObject> fileObjects = new HashMap<URI, JavaFileObject>();
public JavaFileManagerImpl(JavaFileManager fileManager, ClassLoaderImpl classLoader) {
super(fileManager);
this.classLoader = classLoader;
}
@Override
public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
FileObject o = fileObjects.get(uri(location, packageName, relativeName));
if (o != null)
return o;
return super.getFileForInput(location, packageName, relativeName);
}
public void putFileForInput(StandardLocation location, String packageName, String relativeName, JavaFileObject file) {
fileObjects.put(uri(location, packageName, relativeName), file);
}
private URI uri(Location location, String packageName, String relativeName) {
return ClassUtils.toURI(location.getName() + '/' + packageName + '/' + relativeName);
}
@Override
public JavaFileObject getJavaFileForOutput(Location location, String qualifiedName, JavaFileObject.Kind kind, FileObject outputFile)
throws IOException {
JavaFileObject file = new JavaFileObjectImpl(qualifiedName, kind);
classLoader.add(qualifiedName, file);
return file;
}
@Override
public ClassLoader getClassLoader(JavaFileManager.Location location) {
return classLoader;
}
@Override
public String inferBinaryName(Location loc, JavaFileObject file) {
if (file instanceof JavaFileObjectImpl)
return file.getName();
return super.inferBinaryName(loc, file);
}
@Override
public Iterable<JavaFileObject> list(Location location, String packageName, Set<JavaFileObject.Kind> kinds, boolean recurse)
throws IOException {
Iterable<JavaFileObject> result = super.list(location, packageName, kinds, recurse);
// ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
// List<URL> urlList = new ArrayList<URL>();
// Enumeration<URL> e = contextClassLoader.getResources("com");
// while (e.hasMoreElements()) {
// urlList.add(e.nextElement());
// }
ArrayList<JavaFileObject> files = new ArrayList<JavaFileObject>();
if (location == StandardLocation.CLASS_PATH && kinds.contains(JavaFileObject.Kind.CLASS)) {
for (JavaFileObject file : fileObjects.values()) {
if (file.getKind() == JavaFileObject.Kind.CLASS && file.getName().startsWith(packageName)) {
files.add(file);
}
}
files.addAll(classLoader.files());
} else if (location == StandardLocation.SOURCE_PATH && kinds.contains(JavaFileObject.Kind.SOURCE)) {
for (JavaFileObject file : fileObjects.values()) {
if (file.getKind() == JavaFileObject.Kind.SOURCE && file.getName().startsWith(packageName)) {
files.add(file);
}
}
}
for (JavaFileObject file : result) {
files.add(file);
}
return files;
}
}
public static void main(String[] args) throws Throwable {
StringBuilder sb = new StringBuilder();
sb.append("package zhenghui;").append("
");
sb.append("public class Test1{").append("
");
sb.append(" public void printHelloWorld(){").append("
");
sb.append("System.out.println(\"Hello Wolrd\");").append("
");
sb.append(" }").append("
");
sb.append("}").append("
");
JdkCompiler jdkCompiler = new JdkCompiler();
Class clazz = jdkCompiler.doCompile("zhenghui.Test1",sb.toString());
Object obj = clazz.newInstance();
Method method = clazz.getMethod("printHelloWorld");
method.invoke(obj);
}
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
[Python]인터프리터언어?컴파일러언어?compiler : high-lvl prgming language를 low-lvl prgming language(기계어)로 바꾸는, 소스코드를 실행가능한 CPU명령어로 바꾸는 언어 번역 프로그램이다. interpre...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.