### Eclipse Workspace Patch 1.0 #P kato.jdump Index: src/main/java/org/apache/kato/jdump/io/StackDumpWriter.java =================================================================== --- src/main/java/org/apache/kato/jdump/io/StackDumpWriter.java (revision 0) +++ src/main/java/org/apache/kato/jdump/io/StackDumpWriter.java (revision 0) @@ -0,0 +1,218 @@ +/******************************************************************************* + * 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 org.apache.kato.jdump.io; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import javax.tools.diagnostics.image.CorruptDataException; +import javax.tools.diagnostics.image.DataUnavailable; +import javax.tools.diagnostics.runtime.java.JavaStackFrame; +import javax.tools.diagnostics.runtime.java.JavaThread; +import org.apache.kato.jdump.JDump; +import org.apache.kato.model.javaruntime.JThread; + +public class StackDumpWriter { + + private static final String EOL=System.getProperty("line.separator"); + private static final DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + private StringBuilder sb=new StringBuilder(); + + public void write(JDump dump, File file) throws IOException { + sb.append(formatter.format(new Date()) ); + sb.append(EOL); + sb.append("Full thread dump "); + sb.append(System.getProperty("java.vm.vendor")).append(","); + sb.append(System.getProperty("java.vm.name")).append(","); + sb.append(System.getProperty("java.vm.version")); + sb.append(EOL); + sb.append(EOL); + printThreads(dump); + System.out.println(sb.toString()); + BufferedWriter out = new BufferedWriter(new FileWriter(file)); + out.write(sb.toString()); + out.close(); + } + + private void printThreads(JDump dump){ + for (JavaThread javaThread:dump.model.getThreads()){ + printThread(javaThread); + } + } + + private void printThread(JavaThread javaThread){ + printThreadName(javaThread); + sb.append(" "); + printThreadPriority(javaThread); + sb.append(" "); + printThreadPid(javaThread); + //TODO nio + printThreadCondition(javaThread); + printThreadStackTrace(javaThread); + sb.append(EOL); + } + + private void printThreadName(JavaThread javaThread){ + sb.append("\""); + try { + sb.append(javaThread.getName()); + } catch (CorruptDataException e) { + handleCorruptedData(); + } + sb.append("\""); + } + + private void printThreadPriority(JavaThread javaThread){ + sb.append("prio="); + try { + sb.append(javaThread.getPriority()); + } catch (CorruptDataException e) { + handleCorruptedData(); + } + } + + private void printThreadPid(JavaThread javaThread){ + //TODO hex string?? + sb.append("tid=").append(Long.toHexString(((JThread)javaThread).id)); + } + + private void printThreadCondition(JavaThread javaThread){ + String firstClassName=""; + if (isRunnabe(javaThread)){ + sb.append(" runnable [0x0000000000000000]"); + }else{ + try { + StringBuilder fcn=new StringBuilder(); + fcn.append(getClassName(firstClassName=javaThread.getStackFrames().get(0).getLocation().getFilename())); + fcn.append("."); + fcn.append(javaThread.getStackFrames().get(0).getLocation().getMethod().getName()); + firstClassName=fcn.toString(); + } catch (Exception e) { + firstClassName="";// leave name blank + } + if (isObjectWait(firstClassName)){ + sb.append(" in Object.wait() [xxx]"); + } + else if (isThreadParking(firstClassName) || isThreadSleeping(firstClassName)){ + sb.append(" waiting on condition [xxx]"); + } + } + sb.append(EOL); + printThreadState(javaThread); + if (isObjectWait(firstClassName)){ + sb.append(" (on object monitor)"); + }else if (isThreadParking(firstClassName)){ + sb.append(" (parking)"); + }else if (isThreadSleeping(firstClassName)){ + sb.append(" (sleeping)"); + } + } + + private void printThreadState(JavaThread javaThread){ + sb.append("java.lang.Thread.State:"); + String state=""; + int threadState; + try { + threadState=javaThread.getState(); + } catch (CorruptDataException e) { + threadState=0; + } + state=Thread.State.values()[threadState].name(); + sb.append(state); + + } + + private void printThreadStackTrace(JavaThread javaThread){ + sb.append(EOL); + for (JavaStackFrame javaStackFrame:javaThread.getStackFrames()){ + sb.append("at "); + String name=""; + try { + name=javaStackFrame.getLocation().getFilename(); + } catch (DataUnavailable e) { + handleDataUnavailable(); + } catch (CorruptDataException e) { + handleCorruptedData(); + } + sb.append(getClassName(name)); + sb.append("."); + try { + sb.append(javaStackFrame.getLocation().getMethod().getName()); + } catch (CorruptDataException e) { + handleCorruptedData(); + } + sb.append("("); + if (isNativeMethod(javaStackFrame)){ + sb.append("Native Method"); + }else{ + sb.append(name); + sb.append(":"); + try { + sb.append(javaStackFrame.getLocation().getLineNumber()); + } catch (DataUnavailable e) { + handleDataUnavailable(); + } catch (CorruptDataException e) { + handleCorruptedData(); + } + } + sb.append(")"); + sb.append(EOL); + } + } + + private String getClassName(String name){ + return name.substring(0,name.lastIndexOf(".")); + } + + private boolean isNativeMethod(JavaStackFrame javaStackFrame){ + //TODO should be a better way + try { + return javaStackFrame.getLocation().getLineNumber()<1; + } catch (Exception e) { + return false; + } + } + + private boolean isRunnabe(JavaThread javaThread){ + try { + return (javaThread.getState()==1); + } catch (CorruptDataException e) { + return false; + } + } + + private boolean isObjectWait(String method){ + return method.equals("Object.wait"); + } + + private boolean isThreadParking(String method){ + return method.equals("Unsafe.park"); + } + + private boolean isThreadSleeping(String method){ + return method.equals("Thread.sleep"); + } + + private void handleCorruptedData(){ + sb.append("**Corrupted"); + } + + private void handleDataUnavailable(){ + sb.append("**Unavailable"); + } +}