All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.java.btrace.ext.Threads Maven / Gradle / Ivy

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package net.java.btrace.ext;

import net.java.btrace.api.extensions.BTraceExtension;
import java.lang.management.LockInfo;
import java.lang.management.ManagementFactory;
import java.lang.management.MonitorInfo;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
import java.util.Map;
import java.util.Set;
import static net.java.btrace.ext.Printer.*;

/**
 * Provides the threads related methods to BTrace
 * @author Jaroslav Bachorik
 * @since 1.3
 */
@BTraceExtension
public class Threads {

    private static volatile ThreadMXBean threadMBean;

    // Thread and stack access
    /**
     * Tests whether this thread has been interrupted.  The interrupted
     * status of the thread is unaffected by this method.
     *
     * 

A thread interruption ignored because a thread was not alive * at the time of the interrupt will be reflected by this method * returning false. * * @return true if this thread has been interrupted; * false otherwise. */ public static boolean isInteruppted() { return Thread.currentThread().isInterrupted(); } /** * Prints the java stack trace of the current thread. */ public static void jstack() { jstack(-1); } /** * Prints the java stack trace of the current thread. But, * atmost given number of frames. * * @param numFrames number of frames to be printed. When this is * negative all frames are printed. */ public static void jstack(int numFrames) { if (numFrames == 0) { return; } StackTraceElement[] st = Thread.currentThread().getStackTrace(); // passing '5' to skip our own frames to generate stack trace stackTrace(st, 5, numFrames); } /** * Prints Java stack traces of all the Java threads. */ public static void jstackAll() { jstackAll(-1); } /** * Prints Java stack traces of all the Java threads. But, * atmost given number of frames. * * @param numFrames number of frames to be printed. When this is * negative all frames are printed. */ public static void jstackAll(int numFrames) { stackTraceAll(numFrames); } /** * Returns the stack trace of current thread as a String. * * @return the stack trace as a String. */ public static String jstackStr() { return jstackStr(-1); } /** * Returns the stack trace of the current thread as a String * but includes atmost the given number of frames. * * @param numFrames number of frames to be included. When this is * negative all frames are included. * @return the stack trace as a String. */ public static String jstackStr(int numFrames) { if (numFrames == 0) { return ""; } StackTraceElement[] st = Thread.currentThread().getStackTrace(); // passing '5' to skip our own frames to generate stack trace return stackTraceStr(st, 5, numFrames); } /** * Returns the stack traces of all Java threads as a String. * * @return the stack traces as a String. */ public static String jstackAllStr() { return jstackAllStr(-1); } /** * Returns atmost given number of frames in stack traces * of all threads as a String. * * @param numFrames number of frames to be included. When this is * negative all frames are included. * @return the stack traces as a String. */ public static String jstackAllStr(int numFrames) { if (numFrames == 0) { return ""; } return stackTraceAllStr(numFrames); } /** * Prints the stack trace of the given exception object. * * @param exception throwable for which stack trace is printed. */ public static void jstack(Throwable exception) { jstack(exception, -1); } /** * Prints the stack trace of the given exception object. But, * prints at most given number of frames. * * @param exception throwable for which stack trace is printed. * @param numFrames maximum number of frames to be printed. */ public static void jstack(Throwable exception, int numFrames) { if (numFrames == 0) { return; } StackTraceElement[] st = exception.getStackTrace(); println(exception.toString()); stackTrace("\t", st, 0, numFrames); Throwable cause = exception.getCause(); while (cause != null) { println("Caused by:"); st = cause.getStackTrace(); stackTrace("\t", st, 0, numFrames); cause = cause.getCause(); } } /** * Returns the stack trace of given exception object as a String. * * @param exception the throwable for which stack trace is returned. */ public static String jstackStr(Throwable exception) { return jstackStr(exception, -1); } /** * Returns stack trace of given exception object as a String. * * @param exception throwable for which stack trace is returned. * @param numFrames maximum number of frames to be returned. */ public static String jstackStr(Throwable exception, int numFrames) { if (numFrames == 0) { return ""; } StackTraceElement[] st = exception.getStackTrace(); StringBuilder buf = new StringBuilder(); buf.append(exception.toString()); buf.append(stackTraceStr("\t", st, 0, numFrames)); Throwable cause = exception.getCause(); while (cause != null) { buf.append("Caused by:"); st = cause.getStackTrace(); buf.append(stackTraceStr("\t", st, 0, numFrames)); cause = cause.getCause(); } return buf.toString(); } /** * Returns a reference to the currently executing thread object. * * @return the currently executing thread. */ public static Thread currentThread() { return Thread.currentThread(); } /** * Returns the identifier of the given Thread. The thread ID is a positive * long number generated when the given thread was created. * The thread ID is unique and remains unchanged during its lifetime. * When a thread is terminated, the thread ID may be reused. */ public static long threadId(Thread thread) { return thread.getId(); } /** * Returns the state of the given thread. * This method is designed for use in monitoring of the system state, * not for synchronization control. */ public static Thread.State threadState(Thread thread) { return thread.getState(); } /** * Returns true if and only if the current thread holds the * monitor lock on the specified object. * *

This method is designed to allow a program to assert that * the current thread already holds a specified lock: *

     *     assert Thread.holdsLock(obj);
     * 
* * @param obj the object on which to test lock ownership * @throws NullPointerException if obj is null * @return true if the current thread holds the monitor lock on * the specified object. */ public static boolean holdsLock(Object obj) { return Thread.holdsLock(obj); } /** * Prints the Java level deadlocks detected (if any). */ public static void deadlocks() { deadlocks(true); } /** * Prints deadlocks detected (if any). Optionally prints * stack trace of the deadlocked threads. * * @param stackTrace boolean flag to specify whether to * print stack traces of deadlocked threads or not. */ public static void deadlocks(boolean stackTrace) { initThreadMBean(); if (threadMBean.isSynchronizerUsageSupported()) { long[] tids = threadMBean.findDeadlockedThreads(); if (tids != null && tids.length > 0) { ThreadInfo[] infos = threadMBean.getThreadInfo(tids, true, true); StringBuilder sb = new StringBuilder(); for (ThreadInfo ti : infos) { sb.append("\"").append(ti.getThreadName()).append("\"" + " Id=").append(ti.getThreadId()).append(" in ").append(ti.getThreadState()); if (ti.getLockName() != null) { sb.append(" on lock=").append(ti.getLockName()); } if (ti.isSuspended()) { sb.append(" (suspended)"); } if (ti.isInNative()) { sb.append(" (running in native)"); } if (ti.getLockOwnerName() != null) { sb.append(INDENT).append(" owned by ").append(ti.getLockOwnerName()).append(" Id=").append(ti.getLockOwnerId()); sb.append(LINE_SEPARATOR); } if (stackTrace) { // print stack trace with locks StackTraceElement[] stacktrace = ti.getStackTrace(); MonitorInfo[] monitors = ti.getLockedMonitors(); for (int i = 0; i < stacktrace.length; i++) { StackTraceElement ste = stacktrace[i]; sb.append(INDENT).append("at ").append(ste.toString()); sb.append(LINE_SEPARATOR); for (MonitorInfo mi : monitors) { if (mi.getLockedStackDepth() == i) { sb.append(INDENT).append(" - locked ").append(mi); sb.append(LINE_SEPARATOR); } } } sb.append(LINE_SEPARATOR); } LockInfo[] locks = ti.getLockedSynchronizers(); sb.append(INDENT).append("Locked synchronizers: count = ").append(locks.length); sb.append(LINE_SEPARATOR); for (LockInfo li : locks) { sb.append(INDENT).append(" - ").append(li); sb.append(LINE_SEPARATOR); } sb.append(LINE_SEPARATOR); } print(sb.toString()); } } } /** * Returns the name of the given thread. * * @param thread thread whose name is returned */ public static String name(Thread thread) { return thread.getName(); } /** * Returns the current number of live threads including both * daemon and non-daemon threads. * * @return the current number of live threads. */ public static long threadCount() { initThreadMBean(); return threadMBean.getThreadCount(); } /** * Returns the peak live thread count since the Java virtual machine * started or peak was reset. * * @return the peak live thread count. */ public static long peakThreadCount() { initThreadMBean(); return threadMBean.getPeakThreadCount(); } /** * Returns the total number of threads created and also started * since the Java virtual machine started. * * @return the total number of threads started. */ public static long totalStartedThreadCount() { initThreadMBean(); return threadMBean.getTotalStartedThreadCount(); } /** * Returns the current number of live daemon threads. * * @return the current number of live daemon threads. */ public static long daemonThreadCount() { initThreadMBean(); return threadMBean.getDaemonThreadCount(); } /** * Returns the total CPU time for the current thread in nanoseconds. * The returned value is of nanoseconds precision but * not necessarily nanoseconds accuracy. * If the implementation distinguishes between user mode time and system * mode time, the returned CPU time is the amount of time that * the current thread has executed in user mode or system mode. */ public static long currentThreadCpuTime() { initThreadMBean(); threadMBean.setThreadCpuTimeEnabled(true); return threadMBean.getCurrentThreadCpuTime(); } /** * Returns the CPU time that the current thread has executed * in user mode in nanoseconds. * The returned value is of nanoseconds precision but * not necessarily nanoseconds accuracy. */ public static long currentThreadUserTime() { initThreadMBean(); threadMBean.setThreadCpuTimeEnabled(true); return threadMBean.getCurrentThreadUserTime(); } // stack trace functions private static String stackTraceAllStr(int numFrames, boolean printWarning) { Set> traces = Thread.getAllStackTraces().entrySet(); StringBuilder buf = new StringBuilder(); for (Map.Entry t : traces) { buf.append(t.getKey().toString()); buf.append(LINE_SEPARATOR); buf.append(LINE_SEPARATOR); StackTraceElement[] st = t.getValue(); buf.append(stackTraceStr("\t", st, 0, numFrames, printWarning)); buf.append(LINE_SEPARATOR); } return buf.toString(); } private static String stackTraceAllStr(int numFrames) { return stackTraceAllStr(numFrames, false); } private static void stackTraceAll(int numFrames) { print(stackTraceAllStr(numFrames, true)); } private static String stackTraceStr(StackTraceElement[] st, int start, int numFrames) { return stackTraceStr(null, st, start, numFrames, false); } private static String stackTraceStr(String prefix, StackTraceElement[] st, int start, int numFrames) { return stackTraceStr(prefix, st, start, numFrames, false); } private static String stackTraceStr(String prefix, StackTraceElement[] st, int start, int numFrames, boolean printWarning) { start = start > 0 ? start : 0; numFrames = numFrames > 0 ? numFrames : st.length - start; int limit = start + numFrames; limit = limit <= st.length ? limit : st.length; if (prefix == null) { prefix = ""; } StringBuilder buf = new StringBuilder(); for (int i = start; i < limit; i++) { if (prefix != null) { buf.append(prefix); } buf.append(st[i].toString()); buf.append(LINE_SEPARATOR); } if (printWarning && limit < st.length) { if (prefix != null) { buf.append(prefix); } buf.append(st.length - limit); buf.append(" more frame(s) ..."); buf.append(LINE_SEPARATOR); } return buf.toString(); } private static void stackTrace(StackTraceElement[] st, int start, int numFrames) { stackTrace(null, st, start, numFrames); } private static void stackTrace(String prefix, StackTraceElement[] st, int start, int numFrames) { print(stackTraceStr(prefix, st, start, numFrames, true), false); } private static ThreadMXBean getThreadMBean() { try { return AccessController.doPrivileged( new PrivilegedExceptionAction() { public ThreadMXBean run() throws Exception { return ManagementFactory.getThreadMXBean(); } }); } catch (Exception exp) { throw new UnsupportedOperationException(exp); } } private static void initThreadMBean() { if (threadMBean == null) { synchronized (Threads.class) { if (threadMBean == null) { threadMBean = getThreadMBean(); } } } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy