/* * Copyright 2003-2012 Yusuke Yamamoto * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package samurai.core; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; public abstract class FullThreadDump implements Serializable { private List<ThreadDump> threadDumps; private String header; private static final long serialVersionUID = 3698912680951716481L; public FullThreadDump(String header) { this.header = header; threadDumps = new ArrayList<ThreadDump>(); } /*package*/ void addThreadDump(ThreadDump threadDump) { threadDumps.add(threadDump); } public String getHeader() { return header; } public int getThreadCount() { return threadDumps.size(); } public String toString() { StringBuffer toStringed = new StringBuffer(256); toStringed.append(this.header); for (ThreadDump threadDump : threadDumps) { toStringed.append("\n").append(threadDump.toString()); } return toStringed.toString(); } ObjectLock[] objectLocks = null; public ObjectLock[] getObjectLocks() { if(this.objectLocks == null){ List<ObjectLock> objectLockList = new ArrayList<ObjectLock>(); for (Iterator iter = threadDumps.iterator(); iter.hasNext();) { SunThreadDump threadDump = (SunThreadDump) iter.next(); List theLockList = threadDump.getLockedLines(); if (0 != theLockList.size()) { objectLockList.add(new ObjectLock(threadDump, threadDump.getLockedLines())); } } this.objectLocks = new ObjectLock[objectLockList.size()]; for (int i = 0; i < objectLockList.size(); i++) { this.objectLocks[i] = objectLockList.get(i); } } return this.objectLocks; } public ThreadDump getThreadDump(int i) { return threadDumps.get(i); } public ThreadDump getThreadDumpById(String id) { ThreadDump threadDump; for (int i = 0; i < threadDumps.size(); i++) { threadDump = getThreadDump(i); if (id.equals(threadDump.getId())) { return threadDump; } } return null; } /*package*/ abstract boolean isThreadHeader(String line); /*package*/ abstract boolean isThreadFooter(String line); /*package*/ abstract boolean isThreadDumpContinuing(String line); List<List<ThreadDump>> deadLockChains = new ArrayList<List<ThreadDump>>(); private boolean deadLocked = false; public boolean isDeadLocked() { return deadLocked; } public int getDeadLockSize() { return deadLockChains.size(); } public List<List<ThreadDump>> getDeadLockChains() { return deadLockChains; } /*package*/ void finish() { Map<String, ThreadDump> blockers = new HashMap<String, ThreadDump>(); for (ThreadDump threadDump : threadDumps) { List<StackLine> locked = threadDump.getLockedLines(); if (null != locked) { for (StackLine line : locked) { blockers.put(line.getLockedObjectId(), threadDump); } } } Map<String, List<ThreadDump>> locked = new HashMap<String, List<ThreadDump>>(); for (ThreadDump threadDump : threadDumps) { if (threadDump.isBlocked()) { List<ThreadDump> list = locked.get(threadDump.getBlockedObjectId()); if (null == list) { list = new ArrayList<ThreadDump>(); } list.add(threadDump); locked.put(threadDump.getBlockedObjectId(), list); ThreadDump blocker = blockers.get(threadDump.getBlockedObjectId()); if (null != blocker) { threadDump.setBlockerId(blocker.getId()); this.getThreadDumpById(blocker.getId()).setBlocking(true); } } } List<ThreadDump> deadLockChain = new ArrayList<ThreadDump>(); for (ThreadDump threadDump:this.threadDumps) { if (!threadDump.isDeadLocked() && threadDump.isBlocked()) { deadLockChain.clear(); deadLockChain.add(threadDump); while (threadDump.isBlocked()) { String blockerId = threadDump.getBlockerId(); if (null == blockerId) { break; } threadDump = this.getThreadDumpById(blockerId); if (threadDump.isDeadLocked()) { break; } if (deadLockChain.contains(threadDump)) { //deadLockDetected deadLocked = true; int deadLockBegin = deadLockChain.indexOf(threadDump); for (int j = 0; j < deadLockBegin; j++) { deadLockChain.remove(0); } deadLockChains.add(deadLockChain); for (ThreadDump deadLocked : deadLockChain) { deadLocked.setDeadLocked(true); } break; } deadLockChain.add(threadDump); } } } } }