@Override public void terminateProcess(ThreadInfo ti) { SystemState ss = getSystemState(); ThreadInfo[] liveThreads = getLiveThreads(); ThreadInfo finalizerTi = null; for (int i = 0; i < liveThreads.length; i++) { if (!liveThreads[i].isSystemThread()) { // keep the stack frames around, so that we can inspect the snapshot liveThreads[i].setTerminated(); } else { // FinalizerThread is not killed at this point. We need to keep it around in // case fianlizable objects are GCed after System.exit() returns. finalizerTi = liveThreads[i]; } } ss.setMandatoryNextChoiceGenerator( new BreakGenerator("exit", ti, true), "exit without break CG"); // if there is a finalizer thread, we have to run the last GC, to queue finalizable objects, if // any if (finalizerTi != null) { assert finalizerTi.isAlive(); activateGC(); } }
@Override public boolean isDeadlocked() { boolean hasNonDaemons = false; boolean hasBlockedThreads = false; if (ss.isBlockedInAtomicSection()) { return true; // blocked in atomic section } ThreadInfo[] threads = getThreadList().getThreads(); boolean hasUserThreads = false; for (int i = 0; i < threads.length; i++) { ThreadInfo ti = threads[i]; if (ti.isAlive()) { hasNonDaemons |= !ti.isDaemon(); // shortcut - if there is at least one runnable, we are not deadlocked if (ti.isTimeoutRunnable()) { // willBeRunnable() ? return false; } if (!ti.isSystemThread()) { hasUserThreads = true; } // means it is not NEW or TERMINATED, i.e. live & blocked hasBlockedThreads = true; } } boolean isDeadlock = hasNonDaemons && hasBlockedThreads; if (processFinalizers && isDeadlock && !hasUserThreads) { // all threads are blocked, system threads. If the finalizer thread // is in-use, then this is a deadlocked state. return (!getFinalizerThread().isIdle()); } return isDeadlock; }