有人可以帮我解释一下到底发生了什么,请看下面的线程转储。这是一个在Tomcat 7上运行的Web应用程序,我们发现某些请求没有得到回答:

"ajp-bio-8012-exec-161" daemon prio=10 tid=0x00007fe170603000 nid=0x344f runnable [0x00007fe174fae000]
   java.lang.Thread.State: RUNNABLE
    at java.security.AccessController.doPrivileged(Native Method)
    at java.io.FilePermission.init(FilePermission.java:209)
    at java.io.FilePermission.<init>(FilePermission.java:285)
    at java.lang.SecurityManager.checkRead(SecurityManager.java:888)
    at java.io.File.exists(File.java:808)
    at sun.misc.URLClassPath$FileLoader.getResource(URLClassPath.java:1080)
    at sun.misc.URLClassPath$FileLoader.findResource(URLClassPath.java:1047)
    at sun.misc.URLClassPath.findResource(URLClassPath.java:176)
    at java.net.URLClassLoader$2.run(URLClassLoader.java:551)
    at java.net.URLClassLoader$2.run(URLClassLoader.java:549)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findResource(URLClassLoader.java:548)
    at java.lang.ClassLoader.getResource(ClassLoader.java:1147)
    at java.lang.ClassLoader.getResource(ClassLoader.java:1142)
    at org.apache.catalina.loader.WebappClassLoader.getResource(WebappClassLoader.java:1445)
    at java.lang.Class.getResource(Class.java:2142)
    at javassist.ClassClassPath.find(ClassClassPath.java:84)
    at javassist.ClassPoolTail.find(ClassPoolTail.java:317)
    at javassist.ClassPool.find(ClassPool.java:495)
    at javassist.ClassPool.createCtClass(ClassPool.java:479)
    at javassist.ClassPool.get0(ClassPool.java:445)
    - locked <0x00000000db6cdb48> (a javassist.ClassPool)
    at javassist.ClassPool.get(ClassPool.java:414)
    at javassist.compiler.MemberResolver.lookupClass0(MemberResolver.java:425)
    at javassist.compiler.MemberResolver.lookupClass(MemberResolver.java:389)
    at javassist.compiler.MemberResolver.lookupClassByJvmName(MemberResolver.java:310)
    at javassist.compiler.MemberResolver.lookupClass(MemberResolver.java:327)
    at javassist.compiler.MemberResolver.lookupClass(MemberResolver.java:314)
    at javassist.compiler.Javac.compileField(Javac.java:122)
    at javassist.compiler.Javac.compile(Javac.java:91)
    at javassist.CtField.make(CtField.java:163)
    at com.mycompany.validation.util.BeanGenerator.addProperty(BeanGenerator.java:157)
    ...
    at java.lang.Thread.run(Thread.java:745)


"ajp-bio-8012-exec-12" daemon prio=10 tid=0x0000000000c49800 nid=0x3d99 waiting for monitor entry [0x00007fe1756b7000]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at javassist.ClassPool.get0(ClassPool.java:432)
    - waiting to lock <0x00000000db6cdb48> (a javassist.ClassPool)
    at javassist.ClassPool.get(ClassPool.java:414)
    at javassist.compiler.MemberResolver.lookupClass0(MemberResolver.java:425)
    at javassist.compiler.MemberResolver.lookupClass(MemberResolver.java:389)
    at javassist.compiler.MemberResolver.lookupClassByJvmName(MemberResolver.java:310)
    at javassist.compiler.MemberResolver.lookupClass(MemberResolver.java:327)
    at javassist.compiler.MemberResolver.lookupClass(MemberResolver.java:314)
    at javassist.compiler.Javac.compileField(Javac.java:122)
    at javassist.compiler.Javac.compile(Javac.java:91)
    at javassist.CtField.make(CtField.java:163)
    at com.mycompany.validation.util.BeanGenerator.addProperty(BeanGenerator.java:157)
    ...
    at java.lang.Thread.run(Thread.java:745)



"ajp-bio-8012-exec-5" daemon prio=10 tid=0x0000000001603800 nid=0x7c77 waiting for monitor entry [0x00007fe174aaa000]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at javassist.ClassPool.makeClass(ClassPool.java:621)
    - waiting to lock <0x00000000db6cdb48> (a javassist.ClassPool)
    at javassist.ClassPool.makeClass(ClassPool.java:606)
    at com.mycompany.validation.util.BeanGenerator.init(BeanGenerator.java:334)
    ...
    at java.lang.Thread.run(Thread.java:745)


我不是线程转储方面的专家,只是想知道如何解决该问题。

第一个线程是否已锁定其他两个请求线程正在等待解锁的对象(ClassPool)?为什么要锁定?我需要同步吗?如何同步?

感谢您的提示!

最佳答案

您的应用程序中只有一个ClassPool,其监视器ID为0x00000000db6cdb48。

如果看到ClassPool.get0的方法签名:

protected synchronized CtClass get0(String classname, boolean useCache)


因此它是同步的。我想您只是使用了ClassPool.getDefault()。您必须知道此方法返回单个实例,因此所有调用将被同步。

为每个线程创建一个新的池(例如,使用new ClassPool(ClassPool.getDefault())),然后就可以了。

除此之外,您可能还要检查安全管理器,为什么要花这么长时间。

07-24 20:27