/*******************************************************************************
* Copyright (c) 2012 Google, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Google, Inc. - initial API and implementation
*******************************************************************************/
package com.windowtester.internal.debug;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Map.Entry;
import org.eclipse.swt.widgets.Display;
/**
* Thread debugging utility.
*/
public class ThreadUtil
{
private static final Object LOCK = new Object();
private static Timer timer;
/**
* Periodically dump the stack to System.err.
* This automatically cancels any previously scheduled stack dumps.
*/
public static void startPrintStackTraces(long period) {
final Thread callingThread = Thread.currentThread();
synchronized (LOCK) {
stopPrintStackTraces();
timer = new Timer("ThreadUtil Stack Dump");
timer.schedule(new TimerTask() {
public void run() {
System.err.println("**********************************************************************************");
System.err.println("Periodic Thread Dump: " + System.currentTimeMillis());
System.err.println("Default Display Thread: " + Display.getDefault().getThread());
System.err.println("Calling Thread: " + callingThread);
printStackTraces();
}
}, period, period);
}
}
/**
* Stop any scheduled stack dumps
*/
public static void stopPrintStackTraces() {
synchronized (LOCK) {
if (timer != null) {
timer.cancel();
timer = null;
}
}
}
/**
* Get a string representation of the current stack state of all the active threads.
*/
public static String getStackTraces() {
StringWriter stringWriter = new StringWriter(5000);
printStackTraces(new PrintWriter(stringWriter));
return stringWriter.toString();
}
/**
* Print a string representation of the current stack state of all the active threads.
*/
public static void printStackTraces() {
printStackTraces(new PrintWriter(new OutputStreamWriter(System.err)));
}
/**
* Print a string representation of the current stack state of all the active threads.
*/
public static void printStackTraces(PrintWriter writer) {
Map<Thread, StackTraceElement[]> map;
try {
map = Thread.getAllStackTraces();
}
catch (Throwable e) {
writer.println("Failed to obtain stack traces: " + e);
return;
}
if (map == null) {
writer.println("No stack traces available");
return;
}
for (Entry<Thread, StackTraceElement[]> entry : map.entrySet())
printStackTrace(writer, entry.getKey(), entry.getValue());
writer.flush();
}
private static void printStackTrace(PrintWriter writer, Thread thread, StackTraceElement[] trace) {
try {
writer.println(thread.toString() + ":");
for (int i = 0; i < trace.length; i++)
writer.println("\tat " + trace[i]);
}
catch (Exception e) {
writer.println("\t*** Exception printing stack trace: " + e);
}
writer.flush();
}
}