Java编译器通常预先计算最终字段的哈希码吗?

时间:2013-09-27 01:53:56

标签: java optimization compiler-construction

我有一个HashMap密集的Java程序,其中几个类具有从final字段计算的哈希码。例如:

public class Foo {
    private final int bar;
    private final String zot;

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + bar;
        result = prime * result + zot.hashCode();
        return result;
    }
}

编译器可能会在对象初始化后观察到哈希码无法更改,并将其预先计算到另一个private final字段中。当前的Java编译器是否像Oracle JDK 7中那样执行此操作?我可以取消.class文件,但JIT也可以在运行时进行这种优化,我不会在那里看到它。无论如何,我对除了这个之外的其他情况感兴趣,所以找到一种识别编译器自动优化的一般方法会很棒。

3 个答案:

答案 0 :(得分:6)

  

当前的Java编译器是否像Oracle JDK 7中那样执行此操作?

javac几乎没有优化。

  

我可以解散.class文件,

您可能不喜欢在优化方面看到的内容。 ;)

  

但是JIT也可能在运行时进行这种优化,我不会在那里看到它。

如果JIT确实优化了这一点,你就不会看到它,事实上它不会这样做。这就是String在运行时缓存它的hashCode()的原因,明确地在代码中。

答案 1 :(得分:2)

不,编译器不会这样做。但是,将哈希代码自己存储在一个字段中并不难,并且不是一直重新计算而是指代它:

private int hash = -1;

public int hashCode() {
    if (hash == -1) {
        // compute hash, assign it to the hash variable, and return it
    } else {
        return hash;
    }
}

这种方法实际上是由String类进行的,如果你检查它source,你可以看到它:

121  /** Cache the hash code for the string */
122  private int hash; // Default to 0

答案 2 :(得分:1)

编译器可以为任何合适的方法执行此操作,而不仅仅是hashCode(),,但事实并非如此。您可以通过javap -p自行查看是否有任何添加的字段,您还可以使用javap -c查看字节码。

但是,您发布的方法不适合。 String.hashCode()在运行时的实现可能与编译器可用的实现不同。编译器不能假设它不是。