一些正常运行时间后,JDK7应用程序变慢

Jon*_*han 5 performance java-7 jboss7.x

我们在JBoss上使用Hibernate,Spring等几个库部署了一个大型JDK7应用程序.在初始启动服务器之后,应用程序按预期运行,但在一段正常运行时间后,它变得非常慢.

使用分析器,我们已经看到每次外出应用程序的某些方面正在减慢但不总是相同的方面.虽然在一次运行中,hibernate flush可能会慢慢爬行,但在另一次运行中它可能是来自Spring的一些DI代码.

那里发生了什么?

Jon*_*han 9

JDK7中有一个关于CodeCache内存区域的错误,这个错误非常非常困难.

说明

基本上Java启动并使用及时编译(JIT)在运行时期间仅编译字节码的必需部分.这使JVM能够在执行期间取消编译某些代码片段.如果JVM确定,则会发生这种情况,即某个代码片段的初始编译不是最理想的.Oracle 在JDK 7中引入了一个名为分层编译的功能,它允许VM执行此操作.

JVM中的编译代码存储在CodeCache内存区域中.直到JDK6,默认是这个区域将被填满,一旦达到100%,JIT将停止编译并且错误将被打印到控制台,但是应用程序将像以前一样运行:已编译的所有内容将保持编译,尚未编译的所有内容都将在解释模式下执行(大约慢100倍)

此选项已命名CodeCacheFlushing,默认情况下自JDK7u4启用.这个想法是,一旦CodeCache完整,编译代码中使用最少的部分就会从内存中刷新,以便为其他代码片段腾出空间.这将使JDK6-default-behavior(完全停止编译)过时.它还允许一个小得多的CodeCache区域(在JDK7中CodeCache默认为48M/96M,如果启用了分层编译).

这就是bug.在JDK7中,一旦CodeCache满了,JIT就会停止.接下来是CodeCache区域的刷新.而已.冲洗完成后应重新启用JIT,但这不会发生.此外,控制台上没有打印警告.更糟糕的是:在禁用JIT之前,大约一半已编译的代码被抛弃了.

与JDK6相比,快速的所有内容都将保持快速并且只会解释新代码,在JDK7中,您实际上已经丢失了已经编译和优化的代码!应用程序中表现良好的所有突然部分都将停止这样做.这是偶然的,应用程序的哪些部分会变慢,这使得通过探查器跟踪该bugger几乎是不可能的:有时用于刷新的hibernate代码减慢,在其他时候,它的春天DI代码或你自己的appcode.

你受影响了吗?

您可以使用分析器(JProfiler/YourKit)或JConsole(JVisualVM不会这样做)来监视CodeCache内存区域的内存消耗.通常,CodeCache数量committed将保持非常接近的used数量(例如,committed23mb,使用的是22mb).当你的应用程序运行,committedused走,直到committed到达max.那时used将急剧下降到1/2 - 2/3 max.在那之后,used不再生长.这就是虫子会袭击你的地方.在JConsole中,它看起来像这样:

CodeCache内存消耗

为什么我而不是所有其他人?

有可能,你正在使用JBoss.甲骨文很快发现有些东西不应该是tiered compilation默认情况下应该被禁用- 但红帽凭借其无限的智慧决定,它知道更好并重新启用它.基本上我们的webapp在Weblogic上运行良好,只有JBoss受到影响,因为没有分层编译(未在weblogic中启用)CodeCache的增长如此之小,即使经过数周的运行,我们也从未实际达到48mb的阈值.

我能做什么?

首先,决定这个bug是否会袭击你.其次,让虫子更难以伤害你.如果你禁用CodeCacheFlushing至少击中bug就不会让事情变得比以前更糟.停止tiered compilation将使错误击中你的可能性降低,就像增加可用的CodeCache-Memory的数量一样.

您可以随时尝试切换到JDK8,这似乎不受影响,如果CodeCache运行完全,您也可以在软件中实施监控以警告您.

TL; DR

  • 在JDK 7中从不启用分层编译(默认情况下禁用,在JBoss中启用)
  • 在JBoss 7中总是设置PRESERVE_JAVA_OPTS=true在standalone.conf中
  • 总是禁用CodeCacheFlushing(-XX:-UseCodeCacheFlushing)
  • 始终在CodeCache(-XX:ReservedCodeCacheSize=xxM)中包含足够的内存.

  • 链接到JDK问题:http://bugs.java.com/bugdatabase/view_bug.do?video_id = 8012547 (3认同)