/* * 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.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.StringTokenizer; public class ThreadDumpExtractor { private ThreadDumpRenderer renderer; public ThreadDumpExtractor(ThreadDumpRenderer renderer) { this.renderer = renderer; } public void analyze(String threadDump) { StringTokenizer tokenizer = new StringTokenizer(threadDump, "\n"); while (tokenizer.hasMoreTokens()) { analyzeLine(tokenizer.nextToken()); } finish(); } private boolean whileFullThreadDump = false; private boolean whileAthreadDump = false; FullThreadDump fullThreadDump = null; ThreadDump aThreadDump = null; /** * Extracts thread dumps from InputStream and closes it. * @param is - the underlying input stream * @throws IOException - If an I/O error occurs */ public void analyze(InputStream is) throws IOException { BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader(is)); String line; while (null != (line = reader.readLine())) { analyzeLine(line); } } finally { if (null != reader) { try { reader.close(); } catch (IOException ignore) { } } } finish(); } /** * Extracts thread dumps from the specified file * @param file - the file to be examined * @throws IOException - If an I/O error occurs */ public void analyze(File file) throws IOException { analyze(new FileInputStream(file)); } private boolean whileIBMlockInfo = false; private IBMLockInfos ibmLockInfo = null; public void analyzeLine(String line) { checkBeginFullThreadDump(line); if (!whileFullThreadDump && line.startsWith(IBMLockInfos.HEADER)) { whileIBMlockInfo = true; ibmLockInfo = new IBMLockInfos(line); } else if (whileIBMlockInfo) { if (line.startsWith(IBMLockInfos.FOOTER)) { whileIBMlockInfo = false; } else { ibmLockInfo.addLine(line); } } if (whileFullThreadDump) { if (!fullThreadDump.isThreadDumpContinuing(line)) { finish(); // fullThreadDumpEnded(); } else { if (fullThreadDump.isThreadHeader(line)) { if (whileAthreadDump) { //new dump found aThreadDumpEnded(); } aThreadDumpStarted(line); } else if (whileAthreadDump) { if (!fullThreadDump.isThreadFooter(line)) { aThreadDump.addStackLine(line); } else { aThreadDumpEnded(); } } } } } private final int SUN = 0; private final int BEA = 1; private final int IBM = 2; private final String[] FULL_THREAD_DUMP_HEADER = { //SUN "Full thread dump" //BEA , "===== FULL THREAD DUMP ===============" //IBM , "2XMFULLTHDDUMP"}; private int currentJVM = SUN; // private boolean isBEAThreadDump = false; // private int threadDumpIndex = 0; private void checkBeginFullThreadDump(String line) { for (int i = 0; i < FULL_THREAD_DUMP_HEADER.length; i++) { if (line.startsWith(FULL_THREAD_DUMP_HEADER[i])) { currentJVM = i; if (whileAthreadDump) { aThreadDumpEnded(); } if (whileFullThreadDump) { fullThreadDumpEnded(); } fullThreadDumpStarted(line); break; } } } public void finish() { if (whileAthreadDump) { aThreadDumpEnded(); } if (whileFullThreadDump) { fullThreadDumpEnded(); } } private void fullThreadDumpStarted(String header) { switch (this.currentJVM) { case SUN: fullThreadDump = new SunFullThreadDump(header); break; case BEA: fullThreadDump = new BEAFullThreadDump(header); break; case IBM: fullThreadDump = new IBMFullThreadDump(header); break; } whileFullThreadDump = true; } private void fullThreadDumpEnded() { whileFullThreadDump = false; if (null != fullThreadDump) { fullThreadDump.finish(); } renderer.onFullThreadDump(fullThreadDump); } private void aThreadDumpStarted(String header) { switch (currentJVM) { case SUN: aThreadDump = new SunThreadDump(header); break; case BEA: aThreadDump = new BEAThreadDump(header); break; case IBM: aThreadDump = new IBMThreadDump(header, ibmLockInfo); break; default: throw new AssertionError("Illegal JVM Vendor code"); } whileAthreadDump = true; } private void aThreadDumpEnded() { fullThreadDump.addThreadDump(aThreadDump); whileAthreadDump = false; renderer.onThreadDump(aThreadDump); } }