美文网首页
Java 内存动态编译执行

Java 内存动态编译执行

作者: taogan | 来源:发表于2021-03-28 15:52 被阅读0次
public class DynamicCompiler {
    private static final DynamicCompiler DYNAMIC_COMPILER = new DynamicCompiler();

    private DynamicCompiler() {
        if (DYNAMIC_COMPILER != null) {
            throw new AssertionError();
        }
    }

    public static DynamicCompiler getInstance() {
        return DYNAMIC_COMPILER;
    }

    public Object getJavaObject(String name, String code) throws IOException {
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

        // 错误监听信息
        DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();

        // 文件管理器,管理源代码和类文件,负责确定源代码和类文件的实例
        ClassFileManager classFileManager = new ClassFileManager(
                compiler.getStandardFileManager(diagnostics, null, null));

        // Java源文件,可用于读取磁盘之外的数据,如,文本文件,字符串,数据库数据
        JavaSourceFromString sourceFromString = new JavaSourceFromString(name, code);

        JavaCompiler.CompilationTask task = compiler.getTask(
                null, classFileManager, diagnostics, null, null, Arrays.asList(sourceFromString));

        Boolean result = task.call();
        for (Diagnostic<? extends JavaFileObject> diagnostic : diagnostics.getDiagnostics()) {
            throw new DynamicCompilerException(diagnostic.toString());
        }
        classFileManager.close();

        if (result) {
            ByteArrayClassFileObject javaFileObject = classFileManager.getByteArrayClassFileObject();
            DynamicClassLoader dynamicClassLoader = new DynamicClassLoader();
            Class<?> clazz = dynamicClassLoader.loadClass(name, javaFileObject);
            try {
                return clazz.newInstance();
            } catch (ReflectiveOperationException e) {
                e.printStackTrace();
            }
        }
        return null;
    }
}
/**
 * 用于Java编程语言源和类文件的工具的文件管理器。
 * 在这种情况下,文件意味着抽象普通文件和其他数据源。
 */
public class ClassFileManager extends ForwardingJavaFileManager {
    public ClassFileManager(JavaFileManager fileManager) {
        super(fileManager);
    }

    private ByteArrayClassFileObject byteArrayClassFileObject;

    public ByteArrayClassFileObject getByteArrayClassFileObject() {
        return byteArrayClassFileObject;
    }

    @Override
    public JavaFileObject getJavaFileForOutput(Location location, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException {
        return byteArrayClassFileObject = new ByteArrayClassFileObject(className);
    }
}
public class ByteArrayClassFileObject extends SimpleJavaFileObject {
    private final ByteArrayOutputStream outputStream;

    public ByteArrayClassFileObject(String name) {
        super(URI.create("bytes:///" + name), Kind.CLASS);
        outputStream = new ByteArrayOutputStream();
    }

    @Override
    public OutputStream openOutputStream() throws IOException {
        return outputStream;
    }

    public byte[] getBytes() {
        return outputStream.toByteArray();
    }
}
/**
 * 该类提供了一个基本的文件对象实现,可以用作创建文件对象的构建块。
 * 例如,这里是如何定义一个代表存储在一个字符串中的源代码的文件对象:
 */
public class JavaSourceFromString extends SimpleJavaFileObject {

    private final CharSequence code;

    public JavaSourceFromString(String name, CharSequence code) {
        super(URI.create("string:///" + name.replace('.', '/') + Kind.SOURCE.extension),
                Kind.SOURCE);
        this.code = code;
    }

    @Override
    public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
        return code;
    }
}
public class DynamicClassLoader extends ClassLoader {

    public Class loadClass(String fullName, ByteArrayClassFileObject byteArrayClass) {
        byte[] classData = byteArrayClass.getBytes();
        return this.defineClass(fullName, classData, 0, classData.length);
    }
}

public class DynamicCompilerException extends RuntimeException {

    private String message;

    public DynamicCompilerException(String message) {
        super(message);
        this.message = message;
    }

    public DynamicCompilerException(String message, Throwable cause) {
        super(message, cause);
        this.message = message;
    }

    @Override
    public String getMessage() {
        return message;
    }
}

示例
读取文本文件JavaCompilerTest.txt

public class JavaCompilerTest {
    public static void main(String[] args) {
        System.out.println("JavaCompilerTest");
    }
}

运行

    @Test
    public void dy() throws IOException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        DynamicCompiler dynamicCompiler = DynamicCompiler.getInstance();
        byte[] data = Files.readAllBytes(Paths.get("JavaCompilerTest.txt"));
        try {
            Object o = dynamicCompiler.getJavaObject("JavaCompilerTest", new String(data, StandardCharsets.UTF_8));
            Class clazz = o.getClass();
            Method method = clazz.getMethod("main", String[].class);
            method.invoke(null, (Object) new String[]{});
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }

相关文章

  • Java 内存动态编译执行

    示例读取文本文件JavaCompilerTest.txt 运行

  • C语言 基础知识(二)

    静态内存 和 动态内存 分配: 静态内存:是程序编译执行后系统自动分配,由系统自动释放。静态内存是栈分配的。 动态...

  • 2019-03-21

    java源文件编译加载执行过程,jvm内存空间划分

  • 动态执行和静态执行

    动态执行: 在运行期间根据动态信息来确定执行次序。 静态执行: Java虚拟机根据编译期间确定的执行次序顺序执行。

  • 访问者模式讨论篇:java的动态绑定与双分派

    访问者模式讨论篇:java的动态绑定与双分派 java的动态绑定 所谓的动态绑定就是指程执行期间(而不是在编译期间...

  • 让Java代码动态运行

    背景 Java是编译型语言,它不能向JavaScript一样被动态执行,但有时我们却不得不让Java代码能动态运行...

  • 老司机教你如何跨进Python的大门

    1. Python介绍 python = 动态语言java = 静态语言python不用编译,直接解释执行,不用像...

  • JVM之Java内存区域与内存溢出异常

    Java的JVM可以自动管理内存,包括内存动态分配和垃圾收集等。 简介 JVM在执行Java程序的过程中会把它所管...

  • C语言中的动态内存分配

    在编译时分配的内存叫做“静态内存分配”,比如: “动态内存分配”发生在程序调入和执行的时候。 在很多的情况下,我们...

  • 运行时数据区域

    Java虚拟机通过内存动态分配和垃圾收集技术来帮助程序员管理内存。Java虚拟机在执行Java程序的过程中会把它所...

网友评论

      本文标题:Java 内存动态编译执行

      本文链接:https://www.haomeiwen.com/subject/vriphltx.html