4

相同版本的代码优化是否有任何差异: Oracle Java 编译器 Apache Java 编译器 IBM Java 编译器 OpenJDK Java 编译器。如果有什么代码会展示不同的优化?还是他们使用相同的编译器?如果没有已知的优化差异,那么我在哪里可以找到有关如何测试编译器以进行不同优化的资源?

4

3 回答 3

3

不,他们不使用相同的编译器。我不能对优化和东西发表太多评论,但这里有一个例子,编译器在工作中是如何不同的。

public class Test {
    public static void main(String[] args) {
        int x = 1L;  // <- this cannot compile
    }
}

如果你使用标准的 java 编译器,它会抛出一个编译错误并且类文件不会被创建。

但是如果你使用 java ECJ的 eclipse 编译器,它不仅会抛出相同的编译错误,而且还会创建一个类文件(的,一个用于不可编译代码的类文件,这使得 ECJ,我不会说错,但有点棘手),看起来像这样。

public static void main(String[] paramArrayOfString)
{
    throw new Error("Unresolved compilation problem: \n\tType mismatch: cannot convert from long to int.\n");
}

话虽如此,这只是在 2 个编译器之间。其他编译器可能有自己的工作方式。

PS:我从这里举了这个例子。

于 2013-10-02T08:07:40.250 回答
3

相同版本的代码优化是否有任何差异: Oracle Java 编译器 Apache Java 编译器 IBM Java 编译器 OpenJDK Java 编译器。

虽然编译器可能非常不同,javac但几乎没有优化。主要优化是常量内联,这是在 JLS 中指定的,因此是标准的(任何错误除外)

如果有什么代码会展示不同的优化?

你可以这样做。

final String w = "world";
String a = "hello " + w;
String b = "hello world";
String c = w;
String d = "hello " + c;
System.out.prinlnt(a == b); // these are the same String
System.out.prinlnt(c == b); // these are NOT the same String

在第一种情况下,常量被内联并在编译时连接字符串。在第二种情况下,连接是在运行时执行的,并创建了一个新的字符串。

还是他们使用相同的编译器?

不,但 99% 的优化是由 JIT 在运行时执行的,因此对于给定版本的 JVM,这些优化是相同的。

如果没有已知的优化差异,那么我在哪里可以找到有关如何测试编译器以进行不同优化的资源?

如果有一个,我会感到惊讶,因为这听起来不是很有用。问题在于 JIT 优化了字节码的预构建模板,如果您尝试优化字节码,您最终可能会混淆 JIT 并获得较慢的代码。即,如果不考虑将在其上运行的 JVM,就无法评估优化。

于 2013-10-02T08:17:51.873 回答
0

The only compilers that I have spent a great deal of time with are javac (which, as others have pointed out, does very little in terms of eager optimization) and the Eclipse compiler.

While writing a Java decompiler, I have observed a few (often frustrating) differences in how Eclipse compiles code, but not many. Some of them could be considered optimizations. Among them:

  1. The Eclipse compiler appears to perform at least some duplicate code analysis. If two (or more?) blocks of code both branch to separate but equivalent blocks of code, the equivalent target blocks may be flattened into a single block with multiple entry jumps. I have never seen javac perform this type of optimization; the equivalent blocks would always be emitted. All of the examples I can recall happened to occur in switch statements. This optimization reduces the method size (and therefore class file size), which may improve load and verification time. It may even result in improved performance in interpreted mode (particularly if the interpreter in question performs inlining), but I imagine such an improvement would be slight. I doubt it would make a difference once the method has been JIT compiled. It also makes decompilation more difficult (grrr).

  2. Basic blocks are often emitted in a completely different order from javac. This may simply be a side effect of the compiler's internal design, or it may be that the compiler is trying to optimize the code layout to reduce the number of jumps. This is the sort of optimization I would normally leave to the JIT, and that philosophy seems to work fine for javac.

于 2013-10-04T18:57:53.373 回答