Repository navigation
lock find_deadlock
ceragon edited this page Aug 3, 2022
·
3 revisions
class VM_FindDeadlocks: public VM_Operation {
bool _concurrent_locks;
DeadlockCycle* _deadlocks;
outputStream* _out;
ThreadsListSetter _setter;
};class DeadlockCycle : public CHeapObj<mtInternal> {
bool _is_deadlock;
GrowableArray<JavaThread*>* _threads;
DeadlockCycle* _next;
};void VM_FindDeadlocks::doit() {
_setter.set();
_deadlocks = ThreadService::find_deadlocks_at_safepoint(_setter.list(), _concurrent_locks);
if (_out != NULL) {
int num_deadlocks = 0;
for (DeadlockCycle* cycle = _deadlocks; cycle != NULL; cycle = cycle->next()) {
num_deadlocks++;
cycle->print_on_with(_setter.list(), _out);
}
if (num_deadlocks == 1) {
_out->print_cr("\nFound 1 deadlock.\n");
_out->flush();
} else if (num_deadlocks > 1) {
_out->print_cr("\nFound %d deadlocks.\n", num_deadlocks);
_out->flush();
}
}
}下面的方法是在打印死锁信息,打印的内容概括如下:
- 等待获取锁的线程信息
- 锁对象的信息
- 当前持有锁的线程信息
- 持有锁的线程堆栈
void DeadlockCycle::print_on_with(ThreadsList * t_list, outputStream* st) const {
st->cr();
st->print_cr("Found one Java-level deadlock:");
st->print("=============================");
JavaThread* currentThread;
ObjectMonitor* waitingToLockMonitor;
oop waitingToLockBlocker;
int len = _threads->length();
for (int i = 0; i < len; i++) {
currentThread = _threads->at(i);
// 使用 synchronized 会产生 monitor
waitingToLockMonitor = (ObjectMonitor*)currentThread->current_pending_monitor();
// 使用 LockSupport.park() 方法,会把 lock 对象设为 park_blocker
waitingToLockBlocker = currentThread->current_park_blocker();
st->cr();
// 打印线程名称
st->print_cr("\"%s\":", currentThread->get_thread_name());
const char* owner_desc = ",\n which is held by";
if (waitingToLockMonitor != NULL) {
// XX 线程在等待对 monitor XXX 加锁
st->print(" waiting to lock monitor " INTPTR_FORMAT, p2i(waitingToLockMonitor));
// 监视器关联对象
oop obj = (oop)waitingToLockMonitor->object();
if (obj != NULL) {
// 打印对象的地址和类名
st->print(" (object " INTPTR_FORMAT ", a %s)", p2i(obj),
obj->klass()->external_name());
if (!currentThread->current_pending_monitor_is_from_java()) {
// 当前锁不在 java 的栈帧中,所以是在 jni 调用时产生了锁等待
owner_desc = "\n in JNI, which is held by";
}
} else {
// monitor 一定要关联一个对象,但发现没有,则这是一个 jvm 层面的锁
owner_desc = " (JVMTI raw monitor),\n which is held by";
}
// 查一下持有锁的线程是哪个,
currentThread = Threads::owning_thread_from_monitor_owner(t_list,
(address)waitingToLockMonitor->owner());
if (currentThread == NULL) {
// 未知线程持有了锁
st->print("%s UNKNOWN_owner_addr=" PTR_FORMAT, owner_desc,
p2i(waitingToLockMonitor->owner()));
continue;
}
} else {
st->print(" waiting for ownable synchronizer " INTPTR_FORMAT ", (a %s)",
p2i(waitingToLockBlocker),
waitingToLockBlocker->klass()->external_name());
// 另一种锁,但是必须继承 AbstractOwnableSynchronizer 这个类,而且在这个类中记录当前持有锁的线程
oop ownerObj = java_util_concurrent_locks_AbstractOwnableSynchronizer::get_owner_threadObj(waitingToLockBlocker);
currentThread = java_lang_Thread::thread(ownerObj);
}
// 打印持有锁的线程名称
st->print("%s \"%s\"", owner_desc, currentThread->get_thread_name());
}
st->cr();
st->cr();
bool oldJavaMonitorsInStackTrace = JavaMonitorsInStackTrace;
JavaMonitorsInStackTrace = true;
st->print_cr("Java stack information for the threads listed above:");
st->print_cr("===================================================");
// 打印持有锁的线程的堆栈信息
for (int j = 0; j < len; j++) {
currentThread = _threads->at(j);
st->print_cr("\"%s\":", currentThread->get_thread_name());
currentThread->print_stack_on(st);
}
JavaMonitorsInStackTrace = oldJavaMonitorsInStackTrace;
}DeadlockCycle* ThreadService::find_deadlocks_at_safepoint(ThreadsList * t_list, bool concurrent_locks) {
int globalDfn = 0;
int thisDfn;
JavaThreadIterator jti(t_list);
for (JavaThread* jt = jti.first(); jt != NULL; jt = jti.next()) {
// 将所有线程的 depth 设为 -1
jt->set_depth_first_number(-1);
}
DeadlockCycle* cycle = new DeadlockCycle();
for (JavaThread* jt = jti.first(); jt != NULL; jt = jti.next()) {
if (jt->depth_first_number() >= 0) {
// 已经遍历过了
continue;
}
thisDfn = globalDfn;
jt->set_depth_first_number(globalDfn++);
previousThread = jt;
currentThread = jt;
waitingToLockMonitor = (ObjectMonitor*)jt->current_pending_monitor();
if (concurrent_locks) {
waitingToLockBlocker = jt->current_park_blocker();
}
while (waitingToLockMonitor != NULL || waitingToLockBlocker != NULL) {
// currentThread: 等待加锁的线程
cycle->add_thread(currentThread);
if (waitingToLockMonitor != NULL) {
address currentOwner = (address)waitingToLockMonitor->owner();
// 持有锁的线程
currentThread = Threads::owning_thread_from_monitor_owner(t_list,
currentOwner);
} else {
if (concurrent_locks) {
if (waitingToLockBlocker->is_a(SystemDictionary::java_util_concurrent_locks_AbstractOwnableSynchronizer_klass())) {
// 锁对象继承自 AbstractOwnableSynchronizer
oop threadObj = java_util_concurrent_locks_AbstractOwnableSynchronizer::get_owner_threadObj(waitingToLockBlocker);
// 获取持有锁的线程
currentThread = threadObj != NULL ? java_lang_Thread::thread(threadObj) : NULL;
} else {
currentThread = NULL;
}
}
}
}
if (currentThread == NULL) {
break;
}
if (currentThread->depth_first_number() < 0) {
// 首次访问这个线程
currentThread->set_depth_first_number(globalDfn++);
} else if (currentThread->depth_first_number() < thisDfn) {
// 说明这个线程之前被访问过了
break;
} else if (currentThread == previousThread) {
// 锁重入
break;
} else {
// 之所以认定这种情况是发生了死锁,理由如下(假设存在A、B锁):
// 1. 持有 A 锁的线程已经被遍历过了
// 2. 持有 A 锁的线程在等待 B 锁
// 3. B 锁的持有者也在等待某个锁 (可能是 A,也可能不是,不重要)
num_deadlocks++;
cycle->set_deadlock(true);
break;
}
// 会走到这里,说明了 currentThread 是第一次被 visit
previousThread = currentThread;
// 以下是在看 currentThread 有没有正在等待的锁
waitingToLockMonitor = (ObjectMonitor*)currentThread->current_pending_monitor();
if (concurrent_locks) {
waitingToLockBlocker = currentThread->current_park_blocker();
}
}
}