Skip to content

lock find_deadlock

ceragon edited this page Aug 3, 2022 · 3 revisions

jvm 查找死锁

结构体

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();
        }
    }
}

下面的方法是在打印死锁信息,打印的内容概括如下:

  1. 等待获取锁的线程信息
  2. 锁对象的信息
  3. 当前持有锁的线程信息
  4. 持有锁的线程堆栈
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();
        }
    }
}

Clone this wiki locally