Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么JavaCompiler在实例化Java类时速度很慢?_Java_Java Compiler Api_Javacompiler - Fatal编程技术网

为什么JavaCompiler在实例化Java类时速度很慢?

为什么JavaCompiler在实例化Java类时速度很慢?,java,java-compiler-api,javacompiler,Java,Java Compiler Api,Javacompiler,我正在使用JavaCompiler动态创建一个Java类,编译它并加载到我的应用程序中 我的问题是:JavaCompiler的执行时间比实例化同一类的标准方法慢得多 这里有一个例子: static void function() { long startTime = System.currentTimeMillis(); String source = "package myPackage; import java.util.BitSet; public clas

我正在使用JavaCompiler动态创建一个Java类,编译它并加载到我的应用程序中

我的问题是:JavaCompiler的执行时间比实例化同一类的标准方法慢得多

这里有一个例子:

static void function() {
        long startTime = System.currentTimeMillis();
        String source = "package myPackage; import java.util.BitSet; public class MyClass{ static {";

        while (!OWLMapping.axiomStack.isEmpty()) {
            source += OWLMapping.axiomStack.pop() + ";";
        }

        source += "} }";

        File root = new File("/java");
        File sourceFile = new File(root, "myPackage/MyClass.java");
        sourceFile.getParentFile().mkdirs();
        Files.write(sourceFile.toPath(), source.getBytes(StandardCharsets.UTF_8));

        // Compile source file.
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        compiler.run(null, null, null, sourceFile.getPath());

        // Load and instantiate compiled class.
        URLClassLoader classLoader = URLClassLoader.newInstance(new URL[] { root.toURI().toURL() });
        Class<?> cls = Class.forName("myPackage.MyClass", true, classLoader);

        long stopTime = System.currentTimeMillis();
        long elapsedTime = stopTime - startTime;
        System.out.println("EXECUTION TIME: " + elapsedTime);
    }
这正是变量源所包含的内容。
公理的数量取决于用户的输入。

您有两个可能比较慢的区域(但您的基准测试将这两个区域结合起来)

第一个是构建包含源代码的Java
字符串。当跨不同的语句追加字符串时,JVM无法将它们优化到
StringBuilder
s中,这意味着首先在追加的一侧创建字符串,然后在另一侧创建
string
,然后在追加的两个语句中创建第三个
string
。这给堆和垃圾收集带来了很大的压力,产生了大量几乎立即被垃圾收集的对象

要解决第一个问题,请创建一个
StringBuilder
,并调用它的
.append(…)

第二个问题是您正在实例化一个
JavaCompiler
。用于编译Java程序的编译器可能有一个类在顶层驱动它,但它将从大量支持类中获取源代码,以填充其私有字段和嵌入的include。最后,当运行它时,将创建更多的对象来保存代码、词法分析器、解析器、编译单元的AST以及最终的字节码发射器。这意味着一行代码

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
compiler.run(null, null, null, sourceFile.getPath());
可能需要一些时间(同样,他们没有独立进行基准测试)


最后,类装入器行与类装入系统交互,可能对性能适应性较差。虽然这是一个较小的机会,它是一个大的性能打击,我也会基准线独立。

使用
StringBuilder
源代码
While
循环。编译器没有优化循环中的串联。@4castle我怀疑这会有很大的不同。我没有看到您在这里实例化这个类。请记住,当您的代码必须编写源代码时,请将其编译为字节码然后加载,而通常您只执行最后一步。此外,请显示您的其他测试代码。您是否在问为什么编译类并加载它比使用预编译类慢?
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
compiler.run(null, null, null, sourceFile.getPath());