11

我们遇到了一些奇怪的 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(JDK 附带的那个)上使用 64 位 Sun Hotspot JVM。

有谁知道为什么上述方法的执行速度可能比平时慢得多?

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

我附上了分析器的两个屏幕截图。在这两种情况下,我所做的只是在分析器运行时在电子表格单元格周围拖动鼠标。所以它只是更新了 GUI 组件,并没有做太多其他事情。

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

释放锁

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

获取锁

但重要的是,如果我只是更改代码初始化的顺序,这些代码都不会花费很长时间来执行(它甚至根本不会出现在分析器中)。

如果我要优化 getLock() 应用程序仍然执行得慢得多。问题似乎确实是诸如 getClass() 之类的方法花费的时间太长。没有办法弥补这一点 - getClass() 在太多地方被调用!

即使没有运行分析器,性能差异也很明显。

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

4

1 回答 1

1

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

这可能会给Object.getClass().

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

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

于 2013-01-10T19:05:43.543 回答