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

scouter.util.StackUtil Maven / Gradle / Ivy

package scouter.util;

import static java.lang.management.ManagementFactory.THREAD_MXBEAN_NAME;
import static java.lang.management.ManagementFactory.getRuntimeMXBean;
import static java.lang.management.ManagementFactory.getThreadMXBean;
import static java.lang.management.ManagementFactory.newPlatformMXBeanProxy;

import java.io.IOException;
import java.lang.management.LockInfo;
import java.lang.management.MonitorInfo;
import java.lang.management.RuntimeMXBean;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;

import javax.management.MBeanOperationInfo;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;

class StackUtil {
    private MBeanServerConnection server;
    private ThreadMXBean mXBean;
    private ObjectName objName;
    private String headerString;

    private boolean hasDumpAllThreads;

    public StackUtil(MBeanServerConnection server) throws IOException {
        this.server = server;
        this.mXBean = newPlatformMXBeanProxy(server, THREAD_MXBEAN_NAME, ThreadMXBean.class);

        try {
            objName = new ObjectName(THREAD_MXBEAN_NAME);
            checkDumpAllThreads();
            headerString = getHeaderString();
        } catch ( Exception e ) {
            InternalError ie = new InternalError(e.getMessage());
            ie.initCause(e);
            throw ie;
        }
    }
   
    public StackUtil() {
        this.mXBean = getThreadMXBean();
        checkDumpAllThreads();
        headerString = getHeaderString();
    }

    private Properties getSystemProperties() {
        try {
            RuntimeMXBean runtime = getRuntimeMXBean();
            ;
            if ( runtime != null ) {
                Properties prop = new Properties();
                prop.putAll(runtime.getSystemProperties());
                return prop;
            }
            return null;
        } catch ( Exception e ) {
            e.printStackTrace();
        }
        return null;
    }

    public String getHeaderString() {
        Properties prop = getSystemProperties();
        StringBuilder sb = new StringBuilder(100);
        sb.append("Full thread dump ").append(prop.getProperty("java.vm.name")).append(" (").append(prop.getProperty("java.vm.version")).append(' ').append(prop.getProperty("java.vm.info"));
        return sb.toString();
    }

    public List takeThreadDump() throws Exception {
        ThreadMXBean threadMXBean = this.mXBean;
        if ( threadMXBean == null ) {
            return null;
        }

        List list = new ArrayList(100);
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        list.add(df.format(new Date()));
        list.add(headerString);
 
        ThreadInfo[] threads;
        if ( hasDumpAllThreads ) {
            threads = threadMXBean.dumpAllThreads(true, true);
        } else {
            long[] threadIds = threadMXBean.getAllThreadIds();
            threads = threadMXBean.getThreadInfo(threadIds, 2147483647);
        }
        printThreads(list, threadMXBean, threads);
        return list;
    }

    private void printThreads( List list, ThreadMXBean threadMXBean, ThreadInfo[] threads ) {
        boolean jdk16 = hasDumpAllThreads;

        for ( ThreadInfo thread : threads ){
            if ( thread != null ){
                if ( jdk16 )
                    print16Thread(list, threadMXBean, thread);
                else
                    print15Thread(list, thread);
            }
        }
    }

    private void print16Thread( List list, ThreadMXBean threadMXBean, ThreadInfo thread )
    {
        MonitorInfo[] monitors = null;
        if ( threadMXBean.isObjectMonitorUsageSupported() ) {
            monitors = thread.getLockedMonitors();
        }
        list.add("");
        list.add(new StringBuilder(100).append('\"').append(thread.getThreadName()).append("\" - Thread t@").append(thread.getThreadId()).toString());
        list.add("   java.lang.Thread.State: " + thread.getThreadState());
        int index = 0;
        
        StringBuilder sb;
    	LockInfo lock = thread.getLockInfo();
        String lockOwner = thread.getLockOwnerName();
        for ( StackTraceElement st : thread.getStackTrace() ) {
       
        	list.add("\tat " + st.toString());
            
            if ( index == 0 ) {
                if ( ("java.lang.Object".equals(st.getClassName())) && ("wait".equals(st.getMethodName())) )
                {
                    if ( lock != null ) {
                    	sb = new StringBuilder(100);
                        sb.append("\t- waiting on ");
                        printLock(sb, lock);
                        list.add(sb.toString());
                    }
                } else if ( lock != null ) {
                    if ( lockOwner == null ) {
                    	sb = new StringBuilder(100);
                        sb.append("\t- parking to wait for ");
                        printLock(sb, lock);
                    } else {
                    	sb = new StringBuilder(100);
                        sb.append("\t- waiting to lock ");
                        printLock(sb, lock);
                        sb.append(" owned by \"").append(lockOwner).append("\" t@").append(thread.getLockOwnerId());
                        printLock(sb, lock);
                    }
                }
            }
            printMonitors(list, monitors, index);
            index++;
        }
    }

    private void printMonitors( List list, MonitorInfo[] monitors, int index )
    {
        if ( monitors != null )
            for ( MonitorInfo mi : monitors )
                if ( mi.getLockedStackDepth() == index ) {
                	StringBuilder sb = new StringBuilder(100);
                    sb.append("\t- locked ");
                    printLock(sb, mi);
                    list.add(sb.toString());
                }
    }

    private void print15Thread( List list, ThreadInfo thread )
    {
    	list.add("");
    	list.add(new StringBuilder(100).append('\"').append(thread.getThreadName()).append("\" - Thread t@").append(thread.getThreadId()).toString());

    	StringBuilder sb = new StringBuilder(100);
        sb.append("   java.lang.Thread.State: ").append(thread.getThreadState());
        if ( thread.getLockName() != null ) {
            sb.append(" on ").append(thread.getLockName());
            if ( thread.getLockOwnerName() != null ) {
                sb.append(" owned by: ").append(thread.getLockOwnerName());
            }
        }
        list.add(sb.toString());
        for ( StackTraceElement st : thread.getStackTrace() )
            list.add("\tat " + st.toString());
    }

    private void printLock( StringBuilder sb, LockInfo lock )
    {
        sb.append('<').append(Integer.toHexString(lock.getIdentityHashCode())).append("> (a ").append(lock.getClassName()).append(')');
    }

    private void checkDumpAllThreads() {
        synchronized (this) {
            hasDumpAllThreads = false;
            if(server == null){
            	if(System.getProperty("java.version").compareTo("1.5") >= 0){
            		hasDumpAllThreads = true;
            	}
            }else{
	            try {
	                MBeanOperationInfo[] mopis = server.getMBeanInfo(objName).getOperations();
	                if ( mopis != null ) {
	                    for ( MBeanOperationInfo op : mopis ) {
	                        if ( "dumpAllThreads".equals(op.getName()) ) {
	                            hasDumpAllThreads = true;
	                            break;
	                        }
	                    }
	                }
	            } catch ( Exception ex ) {
	                ex.printStackTrace();
	            }
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy