package btools.util; import java.io.BufferedWriter; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStreamWriter; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; import java.util.Map; import java.util.Random; public class StackSampler extends Thread { private DateFormat df = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss,SSS", new Locale( "en", "US" ) ); private BufferedWriter bw; private Random rand = new Random(); private int interval; private int flushCnt = 0; private volatile boolean stopped; public StackSampler( File logfile, int interval ) { this.interval = interval; try { bw = new BufferedWriter( new OutputStreamWriter( new FileOutputStream( logfile, true ) ) ); } catch (Exception e) { printError( "StackSampler: " + e.getMessage() ); } } protected void printError( String msg ) { System.out.println( msg ); } @Override public void run() { while( !stopped ) { dumpThreads(); } if ( bw != null ) { try { bw.close(); } catch( Exception e ) {} } } public void dumpThreads() { try { int wait1 = rand.nextInt( interval ); int wait2 = interval - wait1; Thread.sleep( wait1 ); StringBuilder sb = new StringBuilder( df.format( new Date() ) + " THREADDUMP\n" ); Map allThreads = Thread.getAllStackTraces(); for ( Map.Entry e : allThreads.entrySet() ) { Thread t = e.getKey(); if ( t == Thread.currentThread() ) { continue; // not me } StackTraceElement[] stack = e.getValue(); if ( !matchesFilter( stack ) ) { continue; } sb.append( " (ID=" ).append( t.getId() ).append( " \"" ).append( t.getName() ).append( "\" " ).append( t.getState() ).append( "\n" ); for ( StackTraceElement line : stack ) { sb.append( " " ).append( line.toString() ).append( "\n" ); } sb.append( "\n" ); } bw.write( sb.toString() ); if ( flushCnt++ >= 0 ) { flushCnt = 0; bw.flush(); } Thread.sleep( wait2 ); } catch (Exception e) { // ignore } } public void close() { stopped = true; interrupt(); } private boolean matchesFilter( StackTraceElement[] stack ) { boolean positiveMatch = false; for ( StackTraceElement e : stack ) { String s = e.toString(); if ( s.indexOf( "btools" ) >= 0 ) { positiveMatch = true; } if ( s.indexOf( "Thread.sleep" ) >= 0 ) { return false; } } return positiveMatch; } public static void main( String[] args ) throws Exception { System.out.println( "StackSampler..." ); Class clazz = Class.forName( args[0] ); String[] args2 = new String[args.length - 1]; for ( int i = 1; i < args.length; i++ ) { args2[i - 1] = args[i]; } StackSampler t = new StackSampler( new File( "stacks.log" ), 1000 ); t.start(); try { clazz.getMethod( "main", String[].class ).invoke( null, new Object[]{ args2 } ); } finally { t.close(); } } }