为什么java.lang.Object.getClass()(和反射)比平常慢?

Pau*_*rth 11 java reflection jvm jvm-hotspot

我们遇到了一些奇怪的JVM性能问题.

我们有一个大而有些不透明的GUI组件(Actuate Formula 1电子表格).

如果我们从Event Dispatch Thread初始化它(就像你应该的那样),我们会发现代码的运行速度要慢得多(拖动鼠标选择单元格,会有明显的滞后).

如果我们在主启动器线程中第一次初始化它,然后才开始在EDT中使用它,它运行得更快.

当我查看为什么它使用分析器缓慢执行时,所有时间的方法调用是:

  • java.lang.Object.getClass()
  • java.lang.reflect.Array.newInstance(Class,int)
  • java.lang.Class.getComponentType()
  • java.lang.Thread.currentThread()

我们在Windows 7上使用64位Sun Hotspot JVM(JDK附带的那个).

有没有人知道为什么上述方法的表现可能会比平时慢得多?

我在想,也许它与加载类的顺序有关......这是一个合理的理论吗?有没有人知道我可以诊断为什么这些方法调用可能需要很长时间的任何其他方式?

我已经从探查器附加了两个截图.在两者中,我所做的只是在分析器运行时将鼠标拖动到电子表格单元格周围.所以它只是更新GUI组件而不是做很多其他事情.

第一个是在一个名为"releaseLock()"的方法中花费大量时间.出于某种原因,这需要很长时间,因为"getComponentType()"比平时花费的时间要长得多.

RELEASELOCK

第二个是在我做了"hack"以消除"releaseLock()"的成本之后 - 但现在它只是花了很多时间在"getLock()"中,因为getClass()和currentThread()花费的时间比正常时间长得多:

GETLOCK

但重要的是,如果我只是简单地改变代码初始化的顺序,那么这些代码都不需要很长时间才能执行(它甚至根本不会出现在探查器中).

如果我要优化getLock(),应用程序的执行速度会慢得多.问题实际上似乎是像getClass()这样的方法花费的时间太长了.没有办法弥补这一点 - 在太多的地方调用getClass()!

即使没有运行探查器,性能差异也很明显.

还请记住,我们无法更改任何此代码 - 它是一个外部组件.挑战在于解释为什么代码在某些情况下执行速度比其他情况慢得多.

Vad*_*zim 1

您可以尝试在负载下对应用程序进行多个混合(java+本机) jstack -m线程转储。

这可能会给关于 的幕后发生的事情提供一些提示Object.getClass()

另请参阅如果探查器不是答案,我们还有哪些其他选择?

另请参阅当 JVM 在 GC 中花费时间时,线程转储是什么样子。因为通常的 JVM 线程转储可能并不总是完全准确,因为它们仅发生在安全点上。