<%@ page import="java.lang.management.*,java.lang.Thread.State,java.util.Map,java.util.HashMap,java.util.HashSet"%> <%@page import="java.text.DecimalFormat,java.util.Date,java.util.List"%> <%! /************** page variable and method define start ************************/ final static String versionAndTitle="Thread Checker include GC information v.2010.03.09."; final static int[] optionSeconds={1,3,5,10,20,30,60,600}; final static String numberPattern="###,###,###,###.###"; final static DecimalFormat format=new DecimalFormat(numberPattern); final static String TIME_MS="ms"; final static String TIME_SEC=" sec"; final static String TIME_MIN=" min"; public String getTimeString(long nanoSecond) { long tempMilli=nanoSecond/1000000; if(tempMilli<1000) { return format.format(tempMilli/1000.0)+TIME_MS; } else if(tempMilli<60000) { return format.format(tempMilli/1000.0) +TIME_SEC; } else { return format.format(tempMilli/60000.0) +TIME_MIN; } } final static String SIZE_BYTES=" bytes"; final static String SIZE_KB=" kb"; final static String SIZE_MB=" mb"; final static String memoryPattern="###,###,###,###"; final static DecimalFormat memoryFormat=new DecimalFormat(memoryPattern); public String getMemoryString(long bytes) { if(bytes<1024) { return memoryFormat.format(bytes)+SIZE_BYTES; } else if(bytes<1024*1024) { return memoryFormat.format(bytes/1024) +SIZE_KB; } else { return memoryFormat.format(bytes/(1024*1024)) +SIZE_MB; } } final static String pageWidth="1024";//"100%"; final static String pageWidth2="1000";//"95%"; /************** page variable and method define end ************************/ final static String STRING_STACK_TRACE_INFO_EXTENDED="Ordinal" +"Thread Name" +"Thread State" +"Thread Time" +"Lock Owner" +"Stack Trace information"; final static String STRING_STACK_TRACE_INFO_STANDARD="Ordinal" +"Thread Name" +"Thread State" +"Thread Time"; %> <%=versionAndTitle %> by Sangmin, Lee <% /************** request value check start ************************/ String STRING_AUTO_REFRESH="autoRefresh"; String STRING_REFRESH_SECOND="refreshSecond"; String STRING_VIEW_ALL_THREAD_INFO="viewAllThreadInfo"; String STRING_VIEW_LOCK_INFO="viewLockInfo"; String STRING_STACK_TRACE_NUMBER="stackTraceNumber"; boolean autoRefresh=false; String autoRefreshString=""; String autoRefreshReceive=request.getParameter(STRING_AUTO_REFRESH); if(autoRefreshReceive!=null ) { autoRefresh=true; autoRefreshString=" checked "; //out.println("auto receive="+autoRefreshReceive); } int refreshSecond=3; String refreshSecondReceive=request.getParameter(STRING_REFRESH_SECOND); if(refreshSecondReceive!=null) { refreshSecond=Integer.parseInt(refreshSecondReceive); } boolean viewAllThreadInfo=false; String viewAllThreadInfoString=""; String viewAllThreadInfoReceive=request.getParameter(STRING_VIEW_ALL_THREAD_INFO); if(viewAllThreadInfoReceive!=null) { viewAllThreadInfo=true; viewAllThreadInfoString=" checked "; } boolean viewLockInfo=false; String viewLockInfoString=""; String viewLockInfoReceive=request.getParameter(STRING_VIEW_LOCK_INFO); if(viewLockInfoReceive!=null) { viewLockInfo=true; viewLockInfoString=" checked "; } int stackTraceNumber=100; String stackTraceNumberReceive=request.getParameter(STRING_STACK_TRACE_NUMBER); if(stackTraceNumberReceive!=null) { stackTraceNumber=Integer.parseInt(stackTraceNumberReceive); } /************** request value check end ************************/ %>
<%=versionAndTitle%> by Sangmin, Lee

> Auto Refresh Refresh rate: > View all threads
> View Lock Info
*Server name : <%=application.getServerInfo() %>.    *Last data received time : <%=new Date() %>

<% /*************************** Data Collect start *******************/ //long periodMillis=1000; StringBuffer printDataString=new StringBuffer(); int blocked=0; int newthread=0; int runnable=0; int terminated=0; int timed_waiting=0; int waiting=0; //this attribute is used to change Lock Owner's color HashSet lockOwnerSet=new HashSet(); printDataString.append(""); /********************* check if I can see the lock info ********************************/ if(viewLockInfo) { printDataString.append(STRING_STACK_TRACE_INFO_EXTENDED); } else { printDataString.append(STRING_STACK_TRACE_INFO_STANDARD); } /********************* get ThreadMXBean info ********************************/ ThreadMXBean tmxBean=ManagementFactory.getThreadMXBean(); long threadList[]=tmxBean.getAllThreadIds(); HashMap stackTraceMap=new HashMap(); /********************* get GarbageCollectorMXBean info ********************************/ List gcBeanList=ManagementFactory.getGarbageCollectorMXBeans(); int gcBeanSize=gcBeanList.size(); String gcNames[]=new String[gcBeanSize]; long gcCount[]=new long[gcBeanSize]; double gcTime[]=new double[gcBeanSize]; int gcLoop=0; for(GarbageCollectorMXBean tempGCBean:gcBeanList) { gcNames[gcLoop]=tempGCBean.getName(); gcCount[gcLoop]=tempGCBean.getCollectionCount(); gcTime[gcLoop]=tempGCBean.getCollectionTime()/1000.0; gcLoop++; } /********************* get Stack Traces infos start *******************/ // Because tempThreadInfo.getStackTrace() don't return anything, I use this way if(viewLockInfo) { Map stackInfos=null; stackInfos=Thread.getAllStackTraces(); for (Thread tempThread: stackInfos.keySet()) { stackTraceMap.put(tempThread.getId(),stackInfos.get(tempThread)); } } /********************* get Stack Traces infos end *******************/ try { boolean blockFlag=false; for(long id : threadList) { blockFlag=false; printDataString.append(""); long tempThreadTime=tmxBean.getThreadCpuTime(id); ThreadInfo tempThreadInfo=tmxBean.getThreadInfo(id); String threadName=tempThreadInfo.getThreadName(); State threadState=tempThreadInfo.getThreadState();//.getLockedSynchronizers(); if(threadState==State.BLOCKED) {blocked++; blockFlag=true; } else if(threadState==State.NEW) {newthread++; } else if(threadState==State.RUNNABLE) {runnable++; } else if(threadState==State.TERMINATED) {terminated++; } else if(threadState==State.TIMED_WAITING) {timed_waiting++; } else if(threadState==State.WAITING){ waiting++; } //MonitorInfo[] mis=tempThreadInfo.getLockedMonitors(); int tempOrdinal=threadState.ordinal(); if(viewAllThreadInfo) { //sb.append("
Ordinal="+tempOrdinal+" "+threadName+"=>"+threadState +" ThreadTime="+tempThreadTime); printDataString.append(""); if(blockFlag) { printDataString.append(""); if(viewLockInfo) { printDataString.append(""); printDataString.append(""); } } printDataString.append("\n"); } printDataString.append("
"); printDataString.append(tempOrdinal); printDataString.append(""); printDataString.append(threadName); printDataString.append(""); printDataString.append(""); printDataString.append(threadState); printDataString.append(""); } else { printDataString.append(""); printDataString.append(threadState); } printDataString.append(""); printDataString.append(getTimeString(tempThreadTime)); printDataString.append(""); String lockOwnerName=tempThreadInfo.getLockOwnerName(); if(lockOwnerName!=null) { printDataString.append(lockOwnerName); lockOwnerSet.add(lockOwnerName); } else { printDataString.append(" "); } printDataString.append(""); StackTraceElement[] tempStackTraceElement =stackTraceMap.get(id); int stackTraceSize=tempStackTraceElement.length; if(stackTraceSize!=0) { if(stackTraceSize<=stackTraceNumber) { for (StackTraceElement line: tempStackTraceElement) { printDataString.append(line).append("
"); } } else{ for(int loop=0;loop"); } } } else { printDataString.append(" "); } printDataString.append("
"); out.flush(); //Thread.sleep(periodMillis); } catch(Exception e) { e.printStackTrace(); } MemoryMXBean mbean = ManagementFactory.getMemoryMXBean(); MemoryUsage heapMem=mbean.getHeapMemoryUsage(); MemoryUsage nonHeapMem=mbean.getNonHeapMemoryUsage(); String heapInit=getMemoryString(heapMem.getInit()); String heapUsed=getMemoryString(heapMem.getUsed()); String heapMax=getMemoryString(heapMem.getMax()); String heapCommitted=getMemoryString(heapMem.getCommitted()); /*************************** Data Collect end *******************/ %>
Total Started Thread Count <%=tmxBean.getTotalStartedThreadCount()%> Peak Thread Count <%=tmxBean.getPeakThreadCount()%> Current Thread Count <%=tmxBean.getThreadCount() %> Daemon Thread Count <%= tmxBean.getDaemonThreadCount() %>

<% for(int loop=0;loop <% } %>
GC Name <%=gcNames[loop]%> GC Count <%=gcCount[loop]%> GC Time <%=gcTime[loop] %> sec Average GC Time <%=gcTime[loop]/gcCount[loop] * 1000 %> ms

Heap Used <%=heapUsed%> Heap Min <%=heapInit%> Heap Max <%=heapMax %> Heap Committed <%= heapCommitted %>

Thread State No. of state Description
NEW <%=newthread %> A thread that has not yet started is in this state.
RUNNABLE <%=runnable%> A thread executing in the Java virtual machine is in this state.
BLOCKED <%=blocked%> A thread that is blocked waiting for a monitor lock is in this state.
WAITING <%=waiting%> A thread that is waiting indefinitely for another thread to perform a particular action is in this state.
TIMED_WAITING <%=timed_waiting%> A thread that is waiting for another thread to perform an action for up to a specified waiting time is in this state.
TERMINATED <%=terminated%> A thread that has exited is in this state.

<% if(viewAllThreadInfo) { if(lockOwnerSet.size()!=0) { out.println("* Current Lock Owner List
"); out.println(""); for(String tempOwnerName:lockOwnerSet) { out.println(""); } out.println("
 "+tempOwnerName+" 

"); } %> * All Thread infos
<% out.println(printDataString.toString()); } %>

Copyright Sangmin, Lee. http://www.tuning-java.com All rights Reserved