fgy*_*ica 5 java hibernate weblogic class classloader
我们的项目中存在性能问题,这似乎源于(至少部分)Hibernate 使用类加载器的方式。这是在 Java 线程转储中发现的,这些转储是在我们内部环境的高负载测试期间进行的。转储的 JVM 是运行应用程序的 Weblogic 托管服务器的 JVM,在监控仪表板显示占用线程和待处理用户请求时进行转储。
例子:
"[ACTIVE] ExecuteThread: '126' for queue: 'weblogic.kernel.Default (self-tuning)'" daemon prio=10 tid=0x00007f2fe9486000 nid=0x663b waiting for monitor entry [0x00007f2faeae6000]
java.lang.Thread.State: BLOCKED (on object monitor)
at java.lang.ClassLoader.loadClass(ClassLoader.java:405)
- waiting to lock <0x000000078c0d76b0> (a weblogic.utils.classloaders.GenericClassLoader)
at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
at weblogic.utils.classloaders.GenericClassLoader.loadClass(GenericClassLoader.java:178)
at org.hibernate.internal.util.ReflectHelper.classForName(ReflectHelper.java:187)
at org.hibernate.internal.util.ReflectHelper.getConstantValue(ReflectHelper.java:278)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl$JavaConstantConverter.handleDotStructure(QueryTranslatorImpl.java:592)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl$JavaConstantConverter.visit(QueryTranslatorImpl.java:587)
Run Code Online (Sandbox Code Playgroud)
我们可以在这些线程转储(使用 Samurai/TDA)中看到的是,似乎随时都有大量线程在等待锁定类加载器。这个由 WLS 提供的类加载器似乎是同步的 - 这解释了锁定/阻塞线程模式......
似乎 Hibernate 使用类加载器来评估查询中的表达式。所以我不确定类加载器调用是否真的加载了任何新类。
问题是对类加载器的调用次数似乎一直在进行……有时我观察到多达 30% 的线程总数(~30-40 + 我们的 130)等待获取一个类加载器锁!
-->当大量线程试图为高用户负载(即许多 Hibernate 查询)提供服务时,WLS 类加载器的同步似乎会导致非常高的内部开销。
现在这个同步的类加载器问题似乎是限制我们应用程序吞吐量的主要原因,导致重负载下的性能下降。此外,如果我们扩展 CPU/内存或各种 WLS 特定池(如 EJB/JDBC 连接/...),问题也不会消失——因为它特定于我们运行应用程序的整个 JVM。
我非常感谢您对这个主题的投入。
聚苯乙烯
谷歌似乎表明我们不是第一个遇到这个问题的人(例如这个邮件列表问题或这个 Oracle 支持问题),但是这个问题没有真正的解决方案/解释。
小智 3
问题是应用程序程序员认为 和Class.forName()是Classloader.loadClass()像 a 一样的廉价操作new Object()。并且应用服务器认为它们是罕见的启动操作。
对于 hibernate,使用条件或动态生成的 JPQL 可以触发此锁争用 http://dimovelev.blogspot.dk/2015/02/performance-pitfalls-hibernate-criteria.html