与 Eclipse 编译器相比,为什么 javac 1.5 的运行速度如此之慢? [英] Why is javac 1.5 running so slowly compared with the Eclipse compiler?

查看:22
本文介绍了与 Eclipse 编译器相比,为什么 javac 1.5 的运行速度如此之慢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含大约 800 个源文件(一些由 javacc/JTB 生成)的 Java Maven 项目,使用 javac 编译需要 25 分钟.

I have a Java Maven project with about 800 source files (some generated by javacc/JTB) which is taking a good 25 minutes to compile with javac.

当我将 pom.xml 更改为使用 Eclipse 编译器时,编译需要大约 30 秒.

When I changed my pom.xml over to use the Eclipse compiler, it takes about 30 seconds to compile.

关于为什么 javac (1.5) 运行如此缓慢的任何建议?(我不想永久切换到 Eclipse 编译器,因为 Maven 的插件似乎不仅仅是一个小错误.)

Any suggestions as to why javac (1.5) is running so slowly? (I don't want to switch over to the Eclipse compiler permanently, as the plugin for Maven seems more than a little buggy.)

我有一个可以轻松重现问题的测试用例.以下代码在默认包中生成了许多源文件.如果你尝试用 javac 编译ImplementingClass.java,它似乎会暂停很长时间.

I have a test case which easily reproduces the problem. The following code generates a number of source files in the default package. If you try to compile ImplementingClass.java with javac, it will seem to pause for an inordinately long time.

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintStream;

public class CodeGenerator
{
    private final static String PATH = System.getProperty("java.io.tmpdir");
    private final static int NUM_TYPES = 1000;

    public static void main(String[] args) throws FileNotFoundException
    {
        PrintStream interfacePs = new PrintStream(PATH + File.separator + "Interface.java");
        PrintStream abstractClassPs = new PrintStream(PATH + File.separator + "AbstractClass.java");
        PrintStream implementingClassPs = new PrintStream(PATH + File.separator + "ImplementingClass.java");
        interfacePs.println("public interface Interface<T> {");
        abstractClassPs.println("public abstract class AbstractClass<T> implements Interface<T> {");
        implementingClassPs.println("public class ImplementingClass extends AbstractClass<Object> {");

        for (int i=0; i<NUM_TYPES; i++)
        {
            String nodeName = "Node" + i;
            PrintStream nodePs = new PrintStream(PATH + File.separator + nodeName + ".java");
            nodePs.printf("public class %s { }
", nodeName);
            nodePs.close();
            interfacePs.printf("void visit(%s node, T obj);%n", nodeName);
            abstractClassPs.printf("public void visit(%s node, T obj) { System.out.println(obj.toString()); }%n", nodeName);
        }
        interfacePs.println("}");
        abstractClassPs.println("}");
        implementingClassPs.println("}");
        interfacePs.close();
        abstractClassPs.close();
        implementingClassPs.close();
    }
}

推荐答案

您在 JDK 1.6 中获得了相同的行为,包括更新 14、构建 04,使用 G1 不会改变行为,(尽管 G1 似乎工作得很好).

You get the same behaviour with JDK 1.6, including update 14, build 04, using G1 doesn't change the behaviour, (though G1 appears to work really well).

使用 jvisualvm 监控 javac,重复的线程转储显示主线程在

Monitoring javac with jvisualvm, repeated thread dumps show the main thread spending lots of time in

at com.sun.tools.javac.code.Types.isSubSignature(Types.java:1846)
at com.sun.tools.javac.code.Symbol$MethodSymbol.overrides(Symbol.java:1108)
at com.sun.tools.javac.code.Symbol$MethodSymbol.implementation(Symbol.java:1159)
at com.sun.tools.javac.comp.Check.checkCompatibleConcretes(Check.java:1239)
at com.sun.tools.javac.comp.Check.checkCompatibleSupertypes(Check.java:1567)
at com.sun.tools.javac.comp.Attr.attribClassBody(Attr.java:2674)
at com.sun.tools.javac.comp.Attr.attribClass(Attr.java:2628)
at com.sun.tools.javac.comp.Attr.attribClass(Attr.java:2564)
at com.sun.tools.javac.main.JavaCompiler.attribute(JavaCompiler.java:1036)
at com.sun.tools.javac.main.JavaCompiler.compile2(JavaCompiler.java:765)
at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:730)
at com.sun.tools.javac.main.Main.compile(Main.java:353)
at com.sun.tools.javac.main.Main.compile(Main.java:279)
at com.sun.tools.javac.main.Main.compile(Main.java:270)
at com.sun.tools.javac.Main.compile(Main.java:69)
at com.sun.tools.javac.Main.main(Main.java:54)

并翻阅这些类的大量短命实例:

and churning through a large number of short lived instances of these classes:

com.sun.tools.javac.code.Types$Subst
com.sun.tools.javac.util.List
com.sun.tools.javac.code.Types$MethodType

我怀疑代码正在通过 com.sun.tools.javac.comp.Check.checkCompatibleConcretes 将每种方法与其他方法进行比较

I suspect the code is churning through com.sun.tools.javac.comp.Check.checkCompatibleConcretes comparing each method with every other method

那个方法的javadoc:

That method's javadoc:

/** Check that a class does not inherit two concrete methods
 *  with the same signature.
 */

可能是 eclipse 的编译器没有执行该检查,或者没有以相同的方式执行它.

It may be that eclipse's compiler either doesn't perform that check, or doesn't perform it in the same way.

这篇关于与 Eclipse 编译器相比,为什么 javac 1.5 的运行速度如此之慢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆