`

java内存动态编译执行

    博客分类:
  • Java
 
阅读更多
一般的java的动态编译是需要先生成java文件,然后编译成class,最后用classloader加载进来生成最终的实例的。 
本例程则不需要生成任何文件,一切在内存中进行。
 
标签: <无>
 

代码片段(6)[全屏查看所有代码]

1. [代码][Java]代码     

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package org.jui.core.dynamic;
 
public class DynaCompTest {
    public static void main(String[] args) throws Exception {
        String fullName = "DynaClass";
        StringBuilder src = new StringBuilder();
        src.append("public class DynaClass {\n");
        src.append("    public String toString() {\n");
        src.append("        return \"Hello, I am \" + ");
        src.append("this.getClass().getSimpleName();\n");
        src.append("    }\n");
        src.append("}\n");
 
        System.out.println(src);
        DynamicEngine de = DynamicEngine.getInstance();
        Object instance =  de.javaCodeToObject(fullName,src.toString());
        System.out.println(instance);
    }
}

2. [代码][Java]代码     

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
package org.jui.core.dynamic;
 
import javax.tools.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;
import java.net.URL;
import java.net.URLClassLoader;
import java.io.File;
 
public class DynamicEngine {
    private static DynamicEngine ourInstance = new DynamicEngine();
 
    public static DynamicEngine getInstance() {
        return ourInstance;
    }
    private URLClassLoader parentClassLoader;
    private String classpath;
    private DynamicEngine() {
        this.parentClassLoader = (URLClassLoader) this.getClass().getClassLoader();
        this.buildClassPath();
    }
    private void buildClassPath() {
        this.classpath = null;
        StringBuilder sb = new StringBuilder();
        for (URL url : this.parentClassLoader.getURLs()) {
            String p = url.getFile();
            sb.append(p).append(File.pathSeparator);
        }
        this.classpath = sb.toString();
    }
    public Object javaCodeToObject(String fullClassName, String javaCode) throws IllegalAccessException, InstantiationException {
        long start = System.currentTimeMillis();
        Object instance = null;
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<JavaFileObject>();
        ClassFileManager fileManager = new ClassFileManager(compiler.getStandardFileManager(diagnostics, null, null));
 
        List<JavaFileObject> jfiles = new ArrayList<JavaFileObject>();
        jfiles.add(new CharSequenceJavaFileObject(fullClassName, javaCode));
 
        List<String> options = new ArrayList<String>();
        options.add("-encoding");
        options.add("UTF-8");
        options.add("-classpath");
        options.add(this.classpath);
 
        JavaCompiler.CompilationTask task = compiler.getTask(null, fileManager, diagnostics, options, null, jfiles);
        boolean success = task.call();
 
        if (success) {
            JavaClassObject jco = fileManager.getJavaClassObject();
            DynamicClassLoader dynamicClassLoader = new DynamicClassLoader(this.parentClassLoader);
            Class clazz = dynamicClassLoader.loadClass(fullClassName,jco);
            instance = clazz.newInstance();
        } else {
            String error = "";
            for (Diagnostic diagnostic : diagnostics.getDiagnostics()) {
                error = error + compilePrint(diagnostic);
            }
        }
        long end = System.currentTimeMillis();
        System.out.println("javaCodeToObject use:"+(end-start)+"ms");
        return instance;
    }
 
    private String compilePrint(Diagnostic diagnostic) {
        System.out.println("Code:" + diagnostic.getCode());
        System.out.println("Kind:" + diagnostic.getKind());
        System.out.println("Position:" + diagnostic.getPosition());
        System.out.println("Start Position:" + diagnostic.getStartPosition());
        System.out.println("End Position:" + diagnostic.getEndPosition());
        System.out.println("Source:" + diagnostic.getSource());
        System.out.println("Message:" + diagnostic.getMessage(null));
        System.out.println("LineNumber:" + diagnostic.getLineNumber());
        System.out.println("ColumnNumber:" + diagnostic.getColumnNumber());
        StringBuffer res = new StringBuffer();
        res.append("Code:[" + diagnostic.getCode() + "]\n");
        res.append("Kind:[" + diagnostic.getKind() + "]\n");
        res.append("Position:[" + diagnostic.getPosition() + "]\n");
        res.append("Start Position:[" + diagnostic.getStartPosition() + "]\n");
        res.append("End Position:[" + diagnostic.getEndPosition() + "]\n");
        res.append("Source:[" + diagnostic.getSource() + "]\n");
        res.append("Message:[" + diagnostic.getMessage(null) + "]\n");
        res.append("LineNumber:[" + diagnostic.getLineNumber() + "]\n");
        res.append("ColumnNumber:[" + diagnostic.getColumnNumber() + "]\n");
        return res.toString();
    }
}

3. [代码][Java]代码     

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package org.jui.core.dynamic;
 
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import java.net.URI;
 
public class CharSequenceJavaFileObject extends SimpleJavaFileObject {
 
    private CharSequence content;
 
 
    public CharSequenceJavaFileObject(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) {
        return content;
    }
}

4. [代码][Java]代码     

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
package org.jui.core.dynamic;
 
import javax.tools.*;
import java.io.IOException;
import java.security.SecureClassLoader;
 
public class ClassFileManager extends
        ForwardingJavaFileManager {
    public JavaClassObject getJavaClassObject() {
        return jclassObject;
    }
 
    private JavaClassObject jclassObject;
 
 
    public ClassFileManager(StandardJavaFileManager
        standardManager) {
        super(standardManager);
    }
 
 
    @Override
    public JavaFileObject getJavaFileForOutput(Location location,
        String className, JavaFileObject.Kind kind, FileObject sibling)
            throws IOException {
            jclassObject = new JavaClassObject(className, kind);
        return jclassObject;
    }
}

5. [代码][Java]代码     

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
package org.jui.core.dynamic;
 
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;
import java.io.IOException;
import java.io.OutputStream;
import java.io.ByteArrayOutputStream;
import java.net.URI;
 
public class JavaClassObject extends SimpleJavaFileObject {
 
    protected final ByteArrayOutputStream bos =
        new ByteArrayOutputStream();
 
 
    public JavaClassObject(String name, JavaFileObject.Kind kind) {
        super(URI.create("string:///" + name.replace('.', '/')
            + kind.extension), kind);
    }
 
 
    public byte[] getBytes() {
        return bos.toByteArray();
    }
 
    @Override
    public OutputStream openOutputStream() throws IOException {
        return bos;
    }
}

6. [代码][Java]代码     

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package org.jui.core.dynamic;
 
import java.net.URLClassLoader;
import java.net.URL;
 
public class DynamicClassLoader extends URLClassLoader {
    public DynamicClassLoader(ClassLoader parent) {
        super(new URL[0], parent);
    }
 
    public Class findClassByClassName(String className) throws ClassNotFoundException {
        return this.findClass(className);
    }
 
    public Class loadClass(String fullName, JavaClassObject jco) {
        byte[] classData = jco.getBytes();
        return this.defineClass(fullName, classData, 0, classData.length);
    }
}
分享到:
评论

相关推荐

    内存中动态编译执行java代码

    内存中动态编译执行Java代码是一种高级编程技巧,它允许我们在程序运行时根据需要创建、编译和执行新的Java代码。这种技术在某些场景下非常有用,比如在元编程、插件系统、自定义脚本执行或者代码热更新中。在Java中...

    Java动态编译Java代码,运行在内存中,并执行

    添加动态执行的编译环境 options 是个集合,添加内容,字符集,classpath等 * 6.传入JavaFileObject的java文件,是个集合,创建JavaSourceObject实现这个接口,Kind.SOURCE.extension = '.java' * 7.创建任务并...

    Java类动态加载(一)——java源文件动态编译为class文件

    这篇博客“Java类动态加载(一)——java源文件动态编译为class文件”可能主要探讨了如何在运行时将Java源代码(.java)编译成对应的字节码文件(.class),并将其加载到Java虚拟机(JVM)中。以下是对这个主题的详细解析...

    Java6内存中动态编译案例

    java6提供标准包javax.tools操作Java编译器,本例实现在内存动态编译java代码,并加载动态生成类 执行 console: public class HelloWorld { public static void main(String args[]) { System.out.println("Hello...

    Java运行时动态编译

    首先,理解Java的解释与编译执行过程是关键。Java程序在执行前,会通过Java编译器(javac)将源代码编译为字节码,这是平台无关的中间表示。然后,当Java虚拟机加载这些字节码时,它有两种执行方式:解释执行和编译...

    Java6动态编译案例

    在提供的压缩包文件中,"内存中编译"和"Java6内存中动态编译案例"可能包含了一些实际操作的示例代码,这些代码可能演示了如何在内存中创建源代码字符串,然后使用`JavaCompiler`编译这些源代码,而无需将它们写入...

    JAVA文件编译执行与虚拟机(JVM)介绍

    ### JAVA文件编译执行与虚拟机(JVM)介绍 #### 关键知识点概述: 1. **JAVA文件的编译与执行**:JAVA程序首先通过编译器转换为中间代码(字节码),然后由JVM解释执行。 2. **JVM的角色与功能**:JVM作为JAVA程序...

    动态编译字符串成java,并且添加class到jvm

    使用`Class.forName()`加载类后,可以调用`newInstance()`方法创建类的实例,然后调用其方法执行动态编译的代码。 以上步骤概括了动态编译字符串成Java并加载到JVM的过程。这个技术虽然强大,但也需要注意安全问题...

    动态编译、加载java类

    在Java编程中,动态编译和加载类是一种高级特性,它允许程序在运行时编译源代码并将其加载到Java虚拟机(JVM)中。这种能力对于开发灵活性高、可扩展性强的应用程序非常有用,比如在服务器端处理动态生成的代码、...

    Java程序的编译、加载与执行.zip

    Java程序的编译、加载与执行是理解Java平台工作原理的关键环节。在深入探讨之前,首先需要明确Java程序的基本结构,通常由源代码文件(扩展名为.java)组成,经过编译后生成字节码文件(扩展名为.class)。这些字节...

    java程序的编译与执行

    ### Java程序的编译与执行 #### 深度理解Java虚拟机的操作过程与规范 在探讨Java程序的编译与执行之前,我们先来了解一下Java虚拟机(JVM)的基本概念以及它在整个Java生态系统中的作用。 **Java虚拟机**(JVM)是一...

    java内存分配情况

    Java内存分配主要涉及五个区域:寄存器、栈、堆、静态域和常量池。在Java编程中,理解这些内存区域的分配规则对于优化代码性能和避免内存泄漏至关重要。 1. **寄存器**:这是最快捷的存储区域,但不在Java程序员的...

    Web环境下Java表达式的动态编译与计算.pdf

    本文介绍了一种在Web环境下实现Java表达式的动态编译与计算的方法,该方法利用Java SE 6提供的编译器API实现动态编译,自定义类装载器装入字节代码,并使用反射机制调用计算方法,实现了Java表达式的动态编译与计算...

    java内存模型详解

    Java内存模型,简称JMM(Java Memory Model),是Java虚拟机规范中定义的一个抽象概念,它规定了程序中各个线程如何访问共享变量,以及对这些访问进行同步控制的规则。理解Java内存模型对于编写多线程并发程序至关...

    Java中堆内存与栈内存分配浅析

    本文将深入探讨Java中堆内存与栈内存的分配机制,并通过对比分析它们之间的差异,帮助读者更好地掌握Java内存管理的核心概念。 #### 二、堆内存与栈内存概述 ##### 1. 堆内存 堆内存是Java虚拟机(JVM)用于存储...

    java内存分配 内存泄漏

    理解Java内存分配和JVM工作原理对于开发高效、健壮的Java应用至关重要。开发者应避免内存泄漏,合理使用内存,充分利用JVM的垃圾收集机制,同时理解JIT编译的优化策略,以提高程序的运行性能。在开发过程中,使用...

    Java内存模型分析与其在编程中的应用.pdf

    Java内存模型是Java平台的核心概念之一,它定义了Java程序中各种变量的访问规则以及如何在运行时分配内存区域给对象。Java内存模型的深入分析对于编写高性能的Java应用程序至关重要,本文将详细探讨Java内存模型的...

    深入Java核心_Java内存分配原理精讲

    Java内存分配原理是Java编程中的重要一环,它关乎到程序的性能、稳定性和资源管理。深入理解这一主题,能够帮助开发者编写出更高效、更稳定的代码。在Java中,内存分为堆内存、栈内存、方法区(在Java 8之后被元空间...

Global site tag (gtag.js) - Google Analytics