12.9 AggressiveOpts标志

AggressiveOpts 标志(默认为 false)会影响一些基本 Java 操作的行为。其目标是试验性地引入一些优化;随着时间的推移,原来由这个标志启用的优化有望成为 JVM 的默认设置。很多 Java 6 中的这类优化在 Java 7u4 中都成了默认的设置。在每个 JDK 版本中,都应该重新测试该标志,看看它对应用是否还有积极的影响。

12.9.1 替代实现

启用 AggressiveOpts 标志的主要影响是,它会为 JDK 中的一些基本的类引入不同的替代实现:尤其是 java.math 包中的 BigDecimalBigIntegerMutableBigDecimal 类;java.text 中的 DecimalFormatDigitalListNumberFormat 类;java.util 包中的 HashMapLinkedHashMapTreeMap 类。

这些类在功能上与它们所替代的标准 JDK 中的类是一致的,但是采用了更高效的实现。在 Java 8 中,这些替代实现已经去掉,或者是合并到了基本的 JDK 类中,或者是以其他方式改进了基本的 JDK 类。

之所以要通过设置 AggressiveOpts 标志才能启用这些类(在 Java 7 中),原因在于它们的行为可能会在应用代码中引发一些微妙的 bug。比如,HashMap 类的激进实现所生成的迭代器,其返回键值的顺序与标准实现相比会有所不同。应用首先绝不能依赖该迭代器返回元素的顺序,但现实中很多应用都会犯这个错误。出于兼容性考虑,这种更高效的实现并没有覆盖掉原来的实现,所以必须通过设置 AggressiveOpts 标志来获得更好的性能。

因为 Java 8 去掉了这些类,所以在升级时可能会损害到 bug 兼容性——这又一次暗示了从一开始就写好代码的重要性。

12.9.2 其他标志

开启 AggressiveOpts 标志会影响其他一些较为次要的 JVM 调优。

设置 AggressiveOpts 标志会开启 Autofill 标志(它在 JDK 7 到 7u4 这几个版本中默认为 false)。这个标志开启后,编译器会对循环进行更好的优化。类似地,AggressiveOpts 标志还会开启 DoEscapeAnalysis 标志(在 JDK 7u4 及后续版本中,这个标志也成了默认的)。

AutoBoxCacheMax 标志(默认为 128)被设置为 20 000,支持对更多值进行自动装箱,这会轻微改进特定应用的性能(代价是使用的内存也会稍微增多)。BiasedLockingStartupDelay 会从默认的 2000 减到 500,这意味着偏向锁会在应用开始执行后更短的时间内启用。

最后,该标志还会开启 OptimizeStringConcat 标志,允许 JVM 优化 StringBuilder 对象的使用,具体而言,当编写下面这样的代码时,javac 编译器会创建 StringBuilder 对象:

  1. String s = obj1 + ":" + obj2 + ":" + obj3;

javac 编译器会将这行代码翻译为一个 StringBuilder 对象上的一系列 append() 调用。当 OptimizeStringConcat 标志开启时,JVM 即时编译器(JIT)会把 StringBuilder 对象的创建优化掉。在 JDK 7 到 7u4 的版本中,OptimizeStringConcat 标志默认为 false,而在开启 AggressiveOpts 标志后,其默认值变成了 true

12.9 AggressiveOpts标志 - 图1 快速小结

1. AggressiveOpts 标志会在一些基本的类中开启某些优化。大多数情况下,这些类要快于它们所替代的类,不过可能有意想不到的副作用。

2. Java 8 中去掉了这些类。