如果java层面发生了死锁,当我们使用jstack命令的时候其实是可以将死锁的信息给dump出来的,在dump结果的最后会有类似Found one Java-level deadlock:的关键字,接着会把发生死锁的线程的堆栈及对应的同步锁给打印出来,这次碰到一个系统就发生类似的问题,不过这个dump文档里虽然提到了如下的死锁信息:
1234567891011
Found one Java-level deadlock:
=============================
"worker-1-thread-121":
waiting to lock monitor 0x00007f3758209dc8 (object 0x0000000764cd2b20, a java.util.concurrent.ConcurrentHashMap),
which is held by "HSFBizProcessor-4-thread-4"
"HSFBizProcessor-4-thread-4":
waiting to lock monitor 0x00007f3758289260 (object 0x000000076073ddc8, a com.alipay.cloudengine.extensions.equinox.KernelBundleClassLoader),
which is held by "HSFBizProcessor-4-thread-5"
"HSFBizProcessor-4-thread-5":
waiting to lock monitor 0x00007f3758253420 (object 0x00000007608e6fc8, a com.alipay.cloudengine.extensions.equinox.KernelBundleClassLoader),
which is held by "HSFBizProcessor-4-thread-4"
但是我们在堆栈里搜索对应的锁的时候并没发现,也就是上面提到的
1
object 0x00000007608e6fc8 which is held by "HSFBizProcessor-4-thread-4"
Found one Java-level deadlock:
=============================
"worker-1-thread-121":
waiting to lock monitor 0x00007f3758209dc8 (object 0x0000000764cd2b20, a java.util.concurrent.ConcurrentHashMap),
which is held by "HSFBizProcessor-4-thread-4"
"HSFBizProcessor-4-thread-4":
waiting to lock monitor 0x00007f3758289260 (object 0x000000076073ddc8, a com.alipay.cloudengine.extensions.equinox.KernelBundleClassLoader),
which is held by "HSFBizProcessor-4-thread-5"
"HSFBizProcessor-4-thread-5":
waiting to lock monitor 0x00007f3758253420 (object 0x00000007608e6fc8, a com.alipay.cloudengine.extensions.equinox.KernelBundleClassLoader),
which is held by "HSFBizProcessor-4-thread-4"
Java stack information for the threads listed above:
===================================================
"worker-1-thread-121":
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:180)
- waiting to lock <0x0000000764cd2b20> (a java.util.concurrent.ConcurrentHashMap)
at org.springframework.beans.factory.support.AbstractBeanFactory.isTypeMatch(AbstractBeanFactory.java:455)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:317)
......
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
"HSFBizProcessor-4-thread-4":
at org.eclipse.osgi.baseadaptor.loader.ClasspathManager.findLoadedClass(Unknown Source)
- waiting to lock <0x000000076073ddc8> (a com.alipay.cloudengine.extensions.equinox.KernelBundleClassLoader)
at org.eclipse.osgi.baseadaptor.loader.ClasspathManager.findLocalClass(Unknown Source)
at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.findLocalClass(Unknown Source)
at org.eclipse.osgi.internal.loader.BundleLoader.findLocalClass(Unknown Source)
at org.eclipse.osgi.internal.loader.SingleSourcePackage.loadClass(Unknown Source)
at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(Unknown Source)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(Unknown Source)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(Unknown Source)
at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(Unknown Source)
at com.alipay.cloudengine.extensions.equinox.KernelBundleClassLoader.loadClass(KernelBundleClassLoader.java:121)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
at org.springframework.scripting.groovy.GroovyScriptFactory.executeScript(GroovyScriptFactory.java:238)
......
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
"HSFBizProcessor-4-thread-5":
at org.eclipse.osgi.baseadaptor.loader.ClasspathManager.findLoadedClass(Unknown Source)
- waiting to lock <0x00000007608e6fc8> (a com.alipay.cloudengine.extensions.equinox.KernelBundleClassLoader)
at org.eclipse.osgi.baseadaptor.loader.ClasspathManager.findLocalClass(Unknown Source)
at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.findLocalClass(Unknown Source)
at org.eclipse.osgi.internal.loader.BundleLoader.findLocalClass(Unknown Source)
at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(Unknown Source)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(Unknown Source)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(Unknown Source)
at org.eclipse.osgi.internal.loader.buddy.DependentPolicy.loadClass(Unknown Source)
at org.eclipse.osgi.internal.loader.buddy.PolicyHandler.doBuddyClassLoading(Unknown Source)
at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(Unknown Source)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(Unknown Source)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(Unknown Source)
at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(Unknown Source)
at com.alipay.cloudengine.extensions.equinox.KernelBundleClassLoader.loadClass(KernelBundleClassLoader.java:121)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:169)
at groovy.lang.MetaClassRegistry$MetaClassCreationHandle.createWithCustomLookup(MetaClassRegistry.java:127)
at groovy.lang.MetaClassRegistry$MetaClassCreationHandle.create(MetaClassRegistry.java:122)
......
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
Found 1 deadlock.
类加载的问题?
首先应该怀疑类加载的问题,因为我们看到导致死锁的对象是一个classloader对象:
1
waiting to lock monitor 0x00007f3758289260 (object 0x000000076073ddc8, a com.alipay.cloudengine.extensions.equinox.KernelBundleClassLoader)
然后我们再来分析下堆栈
HSFBizProcessor-4-thread-4
123456789101112131415
"HSFBizProcessor-4-thread-4":
at org.eclipse.osgi.baseadaptor.loader.ClasspathManager.findLoadedClass(Unknown Source)
- waiting to lock <0x000000076073ddc8> (a com.alipay.cloudengine.extensions.equinox.KernelBundleClassLoader)
at org.eclipse.osgi.baseadaptor.loader.ClasspathManager.findLocalClass(Unknown Source)
at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.findLocalClass(Unknown Source)
at org.eclipse.osgi.internal.loader.BundleLoader.findLocalClass(Unknown Source)
at org.eclipse.osgi.internal.loader.SingleSourcePackage.loadClass(Unknown Source)
at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(Unknown Source)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(Unknown Source)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(Unknown Source)
at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(Unknown Source)
at com.alipay.cloudengine.extensions.equinox.KernelBundleClassLoader.loadClass(KernelBundleClassLoader.java:121)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
at org.springframework.scripting.groovy.GroovyScriptFactory.executeScript(GroovyScriptFactory.java:238)
at org.springframework.scripting.groovy.GroovyScriptFactory.getScriptedObject(GroovyScriptFactory.java:185)
我这里只把关键的线程栈贴出来,从栈顶知道正在等一把锁:
1
- waiting to lock <0x000000076073ddc8> (a com.alipay.cloudengine.extensions.equinox.KernelBundleClassLoader)
void TemplateTable::checkcast() {
...
call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc));
...
}
IRT_ENTRY(void, InterpreterRuntime::quicken_io_cc(JavaThread* thread))
// Force resolving; quicken the bytecode
int which = get_index_u2(thread, Bytecodes::_checkcast);
constantPoolOop cpool = method(thread)->constants();
// We'd expect to assert that we're only here to quicken bytecodes, but in a multithreaded
// program we might have seen an unquick'd bytecode in the interpreter but have another
// thread quicken the bytecode before we get here.
// assert( cpool->tag_at(which).is_unresolved_klass(), "should only come here to quicken bytecodes" );
klassOop klass = cpool->klass_at(which, CHECK);
thread->set_vm_result(klass);
IRT_END
klassOop klass_at(int which, TRAPS) {
constantPoolHandle h_this(THREAD, this);
return klass_at_impl(h_this, which, CHECK_NULL);
}
klassOop constantPoolOopDesc::klass_at_impl(constantPoolHandle this_oop, int which, TRAPS) {
...
klassOop k_oop = SystemDictionary::resolve_or_fail(name, loader, h_prot, true, THREAD);
...
}
//SystemDictionary::resolve_or_fail最终会调用到下面这个方法
klassOop SystemDictionary::resolve_instance_class_or_null(Symbol* name, Handle class_loader, Handle protection_domain, TRAPS) {
...
// Class is not in SystemDictionary so we have to do loading.
// Make sure we are synchronized on the class loader before we proceed
Handle lockObject = compute_loader_lock_object(class_loader, THREAD);
check_loader_lock_contention(lockObject, THREAD);
ObjectLocker ol(lockObject, THREAD, DoObjectLock);
...
//此时会调用ClassLoader.loadClass来加载类了
...
}
Handle SystemDictionary::compute_loader_lock_object(Handle class_loader, TRAPS) {
// If class_loader is NULL we synchronize on _system_loader_lock_obj
if (class_loader.is_null()) {
return Handle(THREAD, _system_loader_lock_obj);
} else {
return class_loader;
}
}
"HSFBizProcessor-4-thread-5":
at org.eclipse.osgi.baseadaptor.loader.ClasspathManager.findLoadedClass(Unknown Source)
- waiting to lock <0x00000007608e6fc8> (a com.alipay.cloudengine.extensions.equinox.KernelBundleClassLoader)
at org.eclipse.osgi.baseadaptor.loader.ClasspathManager.findLocalClass(Unknown Source)
at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.findLocalClass(Unknown Source)
at org.eclipse.osgi.internal.loader.BundleLoader.findLocalClass(Unknown Source)
at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(Unknown Source)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(Unknown Source)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(Unknown Source)
at org.eclipse.osgi.internal.loader.buddy.DependentPolicy.loadClass(Unknown Source)
at org.eclipse.osgi.internal.loader.buddy.PolicyHandler.doBuddyClassLoading(Unknown Source)
at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(Unknown Source)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(Unknown Source)
at org.eclipse.osgi.internal.loader.BundleLoader.findClass(Unknown Source)
at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(Unknown Source)
at com.alipay.cloudengine.extensions.equinox.KernelBundleClassLoader.loadClass(KernelBundleClassLoader.java:121)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:169)