Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/309.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 来自Hibernate的同步类加载器调用_Java_Hibernate_Class_Weblogic_Classloader - Fatal编程技术网

Java 来自Hibernate的同步类加载器调用

Java 来自Hibernate的同步类加载器调用,java,hibernate,class,weblogic,classloader,Java,Hibernate,Class,Weblogic,Classloader,我们的项目中存在一个性能问题,它似乎起源于(至少部分)Hibernate使用类加载器的方式。这是在Java线程转储中发现的,这些转储是在内部环境的高负载测试期间进行的。转储的JVM是运行应用程序的Weblogic托管服务器的JVM,转储是在监视仪表板显示占用的线程和挂起的用户请求时进行的 例如: “[ACTIVE]ExecuteThread:'126'用于队列:'weblogic.kernel.Default(自调优)'”守护进程prio=10 tid=0x00007f2fe9486000 ni

我们的项目中存在一个性能问题,它似乎起源于(至少部分)Hibernate使用类加载器的方式。这是在Java线程转储中发现的,这些转储是在内部环境的高负载测试期间进行的。转储的JVM是运行应用程序的Weblogic托管服务器的JVM,转储是在监视仪表板显示占用的线程和挂起的用户请求时进行的

例如:

“[ACTIVE]ExecuteThread:'126'用于队列:'weblogic.kernel.Default(自调优)'”守护进程prio=10 tid=0x00007f2fe9486000 nid=0x663b等待监视器条目[0x00007f2faeae6000]
java.lang.Thread.State:阻塞(在对象监视器上)
位于java.lang.ClassLoader.loadClass(ClassLoader.java:405)
-等待锁定(weblogic.utils.classloaders.GenericClassLoader)
位于java.lang.ClassLoader.loadClass(ClassLoader.java:358)
在weblogic.utils.classloaders.GenericClassLoader.loadClass(GenericClassLoader.java:178)
位于org.hibernate.internal.util.ReflectHelper.classForName(ReflectHelper.java:187)
位于org.hibernate.internal.util.ReflectHelper.getConstantValue(ReflectHelper.java:278)
位于org.hibernate.hql.internal.ast.QueryTranslatorImpl$JavaConstantConverter.handleDotStructure(QueryTranslatorImpl.java:592)
访问org.hibernate.hql.internal.ast.QueryTranslatorImpl$JavaConstantConverter.visit(QueryTranslatorImpl.java:587)
在这些线程转储(使用Samurai/TDA)中,我们可以看到,任何时候都有大量线程在等待类加载器上的锁。WLS提供的这个类加载器似乎是同步的-这解释了锁定/阻塞线程模式

Hibernate似乎使用类加载器来计算查询中的表达式。所以我不确定classloader调用是否真的加载了任何新类

问题是调用类加载器的次数似乎一直在进行。。。有时,我观察到多达30%的线程(约30-40+130个线程)在等待获得类加载器锁

-->当大量线程试图为高用户负载(即许多Hibernate查询)提供服务时,WLS类加载器的同步似乎会导致非常高的内部开销

这种行为是正常的还是我们做错了什么? 目前,这个同步类加载器问题似乎是限制应用程序吞吐量的主要原因,导致在重载情况下性能下降。此外,如果我们扩展CPU/内存或各种特定于WLS的池(如EJB/JDBC连接/…),问题也不会消失,因为它特定于我们运行应用程序的整个JVM

我非常感谢你对这个话题的意见


附言


谷歌似乎表明,我们不是第一个遇到这个问题的人(例如or),但这个问题没有真正的解决方案/解释。

问题是,应用程序程序员认为
Class.forName()
Classloader.loadClass()
是像
新对象()
一样廉价的操作。应用服务器认为它们是一种罕见的启动操作

对于hibernate,使用条件或动态生成的JPQL可以触发此锁争用

Hibernate Jira上多次报告了此问题:

Class.forName
不是免费的。根据基础应用程序服务器的不同,它可能导致锁争用,如所示

Pierre Hugues Charbonneau对此主题有自己的见解,这也是一本精彩的读物


Jira问题已在中修复,这应该不再是问题。

jdk1.6 java.lang.ClassLoader的loadClass已同步

protected synchronized Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
受保护的同步类loadClass(字符串名称,布尔解析)
抛出ClassNotFoundException
jdk1.7使每个类名都有一个锁,这更有效

protected Class<?> loadClass(String name, boolean resolve)throws ClassNotFoundException{
   synchronized (getClassLoadingLock(name)) 
受保护的类loadClass(字符串名称,布尔解析)引发ClassNotFoundException{
已同步(getClassLoadingLock(名称))

堆栈跟踪中的getConstantValue在任何情况下都是重要的。我可以想象这会导致类锁而不是实例锁。我什么都不知道:)你用CAT工具做过分析吗?关于类缓存呢?@NielsBechNielsen嗯,
getConstantValue
的调用经常发生,但到目前为止还没有发生所有这些阻塞类加载器调用。@castling我不知道CAT-一定会尝试一下!这个问题已经转移到了好链接,谢谢!最后对这个问题进行了清晰简洁的解释。可惜的是,唯一的解决方案似乎是放弃criteria API或weblogic。
protected Class<?> loadClass(String name, boolean resolve)throws ClassNotFoundException{
   synchronized (getClassLoadingLock(name))