Dynamic Compiler动态编译源代码(无需File)


import com.google.common.base.Charsets;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;

import javax.tools.*;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author qbit
 */
public class DynamicCompiler {

    private final DynamicClassLoader classLoader;
    public ClassLoader getClassLoader(){
        return classLoader;
    }
    public DynamicCompiler(ClassLoader classLoader){
        this.classLoader=new DynamicClassLoader(classLoader);
    }
    public Class<?> compile(String className,String src){
        JavaCompiler compiler= ToolProvider.getSystemJavaCompiler();
        DiagnosticCollector<javax.tools.JavaFileObject> diagnosticCollector=new DiagnosticCollector<>();
        var standardFileManager=compiler.getStandardFileManager(diagnosticCollector,null,null);
        var javaFileManager=new JavaFileManager(standardFileManager);
        var files= Lists.newArrayList(new JavaFileObject(className,src));
//        var classpath= Joiner.on(File.pathSeparator).join(Stream.of(getParentClassloader().getURLs()).map(URL::getFile).collect(Collectors.toList()));
//        var options=Lists.newArrayList("-encoding", Charsets.UTF_8.toString(),"-classpath",classpath);
        var options=Lists.newArrayList("-encoding", Charsets.UTF_8.toString());
        var task=compiler.getTask(null,javaFileManager,diagnosticCollector,options,null,files);
        if(task.call()){
            return javaFileManager.toClass(classLoader);
        }else{
            String message="compile "+className+" fail!";
            System.err.println(message);
            System.err.println(src);
            diagnosticCollector.getDiagnostics().forEach(diagnostic -> {
                System.err.println("Code:" + diagnostic.getCode());
                System.err.println("Kind:" + diagnostic.getKind());
                System.err.println("Position:" + diagnostic.getPosition());
                System.err.println("Start Position:" + diagnostic.getStartPosition());
                System.err.println("End Position:" + diagnostic.getEndPosition());
                System.err.println("Source:" + diagnostic.getSource());
                System.err.println("Message:" + diagnostic.getMessage(null));
                System.err.println("LineNumber:" + diagnostic.getLineNumber());
                System.err.println("ColumnNumber:" + diagnostic.getColumnNumber());
            });
            throw new RuntimeException(message);
        }
    }
    private class JavaFileObject extends SimpleJavaFileObject{

        private final CharSequence content;

        protected JavaFileObject(String className, CharSequence content) {
            super(URI.create("string:///" + className.replace('.', '/')
                    + JavaFileObject.Kind.SOURCE.extension), JavaFileObject.Kind.SOURCE);
            this.content = content;
        }

        @Override
        public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
            return content;
        }
    }
    private class JavaFileManager extends ForwardingJavaFileManager<javax.tools.JavaFileManager> {

        private JavaClassObject javaFileObject;

        protected JavaFileManager(javax.tools.JavaFileManager fileManager) {
            super(fileManager);
        }

        @Override
        public javax.tools.JavaFileObject getJavaFileForOutput(Location location, String className, javax.tools.JavaFileObject.Kind kind, FileObject sibling) throws IOException {
            javaFileObject=new JavaClassObject(className,kind);
            return javaFileObject;
        }

        public Class<?> toClass(DynamicClassLoader classLoader) {
            return javaFileObject.toClass(classLoader);
        }
    }
    private class JavaClassObject extends SimpleJavaFileObject{
        private final ByteArrayOutputStream bos=new ByteArrayOutputStream();
        private final String name;
        protected JavaClassObject(String name, Kind kind) {
            super(URI.create("string:///" + name.replace('.', '/')
                    + kind.extension), kind);
            this.name=name;
        }

        @Override
        public OutputStream openOutputStream() throws IOException {
            return bos;
        }
        Class<?> toClass(DynamicClassLoader dynamicClassLoader){
            return dynamicClassLoader.defineClass(name,bos.toByteArray());
        }
    }

    private class DynamicClassLoader extends URLClassLoader {

        public DynamicClassLoader(ClassLoader parent) {
            super(new URL[0], parent);
        }

        @Override
        public Class<?> findClass(String name) throws ClassNotFoundException {
            return super.findClass(name);
        }
        public Class<?> defineClass(String name,byte[] bytes){
            return defineClass(name,bytes,0,bytes.length);
        }
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值