001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.oozie.servlet; 019 020import java.io.Serializable; 021import java.lang.Thread.State; 022import java.lang.management.ClassLoadingMXBean; 023import java.lang.management.ManagementFactory; 024import java.lang.management.MemoryMXBean; 025import java.lang.management.MemoryUsage; 026import java.lang.management.ThreadInfo; 027import java.lang.management.ThreadMXBean; 028import java.util.ArrayList; 029import java.util.Collection; 030import java.util.Collections; 031import java.util.Comparator; 032import java.util.Date; 033import java.util.HashMap; 034import java.util.List; 035import java.util.Map; 036 037@SuppressWarnings("serial") 038public class JVMInfo implements Serializable { 039 040 private static Map<State, Integer> threadStateOrdering; 041 private final MemoryMXBean memoryMXBean; 042 private final ClassLoadingMXBean classLoadingMXBean; 043 private final ThreadMXBean threadMXBean; 044 private List<JThreadInfo> jThreadInfos; 045 private String threadSortOrder; 046 private Integer cpuMonitorTime = 0; 047 private int blockedThreads = 0; 048 private int runnableThreads = 0; 049 private int waitingThreads = 0; 050 private int timedWaitingThreads = 0; 051 private int newThreads = 0; 052 private int terminatedThreads = 0; 053 054 static { 055 threadStateOrdering = new HashMap<State, Integer>(); 056 threadStateOrdering.put(State.RUNNABLE, 1); 057 threadStateOrdering.put(State.BLOCKED, 2); 058 threadStateOrdering.put(State.WAITING, 3); 059 threadStateOrdering.put(State.TIMED_WAITING, 4); 060 threadStateOrdering.put(State.NEW, 5); 061 threadStateOrdering.put(State.TERMINATED, 6); 062 } 063 064 public JVMInfo() { 065 memoryMXBean = ManagementFactory.getMemoryMXBean(); 066 classLoadingMXBean = ManagementFactory.getClassLoadingMXBean(); 067 threadMXBean = ManagementFactory.getThreadMXBean(); 068 } 069 070 public String getThreadSortOrder() { 071 return threadSortOrder; 072 } 073 074 public void setThreadSortOrder(String threadSortOrder) { 075 this.threadSortOrder = threadSortOrder; 076 } 077 078 public String getCpuMonitorTime() { 079 return cpuMonitorTime.toString(); 080 } 081 082 public void setCpuMonitorTime(String sleepTime) { 083 if (sleepTime != null) { 084 this.cpuMonitorTime = Integer.parseInt(sleepTime); 085 } 086 } 087 088 public String getHeapMemoryUsage() { 089 MemoryUsage hmu = memoryMXBean.getHeapMemoryUsage(); 090 StringBuffer sb = new StringBuffer(60); 091 sb.append("INIT=").append(hmu.getInit()); 092 sb.append(" USED=").append(hmu.getUsed()); 093 sb.append(" COMMITTED=").append(hmu.getCommitted()); 094 sb.append(" MAX=").append(hmu.getMax()); 095 return sb.toString(); 096 } 097 098 public String getNonHeapMemoryUsage() { 099 MemoryUsage nhmu = memoryMXBean.getNonHeapMemoryUsage(); 100 StringBuffer sb = new StringBuffer(60); 101 sb.append("INIT=").append(nhmu.getInit()); 102 sb.append(" USED=").append(nhmu.getUsed()); 103 sb.append(" COMMITTED=").append(nhmu.getCommitted()); 104 sb.append(" MAX=").append(nhmu.getMax()); 105 return sb.toString(); 106 } 107 108 public String getClassLoadingInfo() { 109 StringBuffer sb = new StringBuffer(150); 110 sb.append("Total Loaded Classes=").append(classLoadingMXBean.getTotalLoadedClassCount()); 111 sb.append(" Loaded Classes=").append(classLoadingMXBean.getLoadedClassCount()); 112 sb.append(" Unloaded Classes=").append(classLoadingMXBean.getUnloadedClassCount()); 113 return sb.toString(); 114 } 115 116 public String getThreadInfo() throws InterruptedException { 117 getThreads(); 118 StringBuffer sb = new StringBuffer(150); 119 sb.append("Thread Count=").append(threadMXBean.getThreadCount()); 120 sb.append(" Peak Thread Count=").append(threadMXBean.getPeakThreadCount()); 121 sb.append(" Total Started Threads=").append(threadMXBean.getTotalStartedThreadCount()); 122 sb.append(" Deamon Threads=").append(threadMXBean.getDaemonThreadCount()); 123 sb.append("<br /> RUNNABLE=").append(runnableThreads); 124 sb.append(" BLOCKED=").append(blockedThreads); 125 sb.append(" WAITING=").append(waitingThreads); 126 sb.append(" TIMED_WAITING=").append(timedWaitingThreads); 127 sb.append(" NEW=").append(newThreads); 128 sb.append(" TERMINATED=").append(terminatedThreads); 129 sb.append("<br /> Time of Thread Dump=").append(new Date().toString()); 130 return sb.toString(); 131 } 132 133 public Collection<JThreadInfo> getThreads() throws InterruptedException { 134 if (jThreadInfos == null) { 135 jThreadInfos = getThreadInfos(); 136 Collections.sort(jThreadInfos, new ThreadComparator(threadSortOrder)); 137 } 138 return jThreadInfos; 139 } 140 141 private List<JThreadInfo> getThreadInfos() throws InterruptedException { 142 ThreadInfo[] threads = threadMXBean.dumpAllThreads(false, false); 143 Map<Long, JThreadInfo> oldThreadInfoMap = new HashMap<Long, JThreadInfo>(); 144 for (ThreadInfo thread : threads) { 145 long cpuTime = -1L; 146 long userTime = -1L; 147 long threadId = thread.getThreadId(); 148 if (threadMXBean.isThreadCpuTimeSupported() && threadMXBean.isThreadCpuTimeEnabled()) { 149 cpuTime = threadMXBean.getThreadCpuTime(threadId); 150 userTime = threadMXBean.getThreadUserTime(threadId); 151 } 152 oldThreadInfoMap.put(thread.getThreadId(), new JThreadInfo(cpuTime, userTime, thread)); 153 } 154 Thread.sleep(cpuMonitorTime); 155 ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false); 156 List<JThreadInfo> jThreadInfos = new ArrayList<JThreadInfo>(threadInfos.length); 157 for (int i = 0; i < threadInfos.length; i++) { 158 ThreadInfo threadInfo = threadInfos[i]; 159 long threadId = threadInfo.getThreadId(); 160 long cpuTime = -1L; 161 long userTime = -1L; 162 if (threadMXBean.isThreadCpuTimeSupported() && threadMXBean.isThreadCpuTimeEnabled()) { 163 JThreadInfo oldThread = oldThreadInfoMap.get(threadInfo.getThreadId()); 164 if (oldThread == null) { 165 cpuTime = threadMXBean.getThreadCpuTime(threadId); 166 userTime = threadMXBean.getThreadUserTime(threadId); 167 } 168 else { 169 cpuTime = threadMXBean.getThreadCpuTime(threadId) - oldThread.getCpuTime(); 170 userTime = threadMXBean.getThreadUserTime(threadId) - oldThread.getUserTime(); 171 } 172 } 173 jThreadInfos.add(new JThreadInfo(cpuTime, userTime, threadInfo)); 174 switch (threadInfo.getThreadState()) { 175 case RUNNABLE: 176 runnableThreads++; 177 break; 178 case BLOCKED: 179 blockedThreads++; 180 break; 181 case WAITING: 182 waitingThreads++; 183 break; 184 case TIMED_WAITING: 185 timedWaitingThreads++; 186 break; 187 case NEW: 188 newThreads++; 189 break; 190 case TERMINATED: 191 terminatedThreads++; 192 break; 193 } 194 } 195 return jThreadInfos; 196 } 197 198 public static final class JThreadInfo { 199 private long cpuTime; 200 private long userTime; 201 private ThreadInfo threadInfo; 202 203 public JThreadInfo(long cpuTime, long userTime, ThreadInfo threadInfo) { 204 this.cpuTime = cpuTime; 205 this.userTime = userTime; 206 this.threadInfo = threadInfo; 207 } 208 209 public long getCpuTime() { 210 return cpuTime; 211 } 212 213 public long getUserTime() { 214 return userTime; 215 } 216 217 public ThreadInfo getThreadInfo() { 218 return threadInfo; 219 } 220 221 } 222 223 private static final class ThreadComparator implements Comparator<JThreadInfo> { 224 225 private String threadSortOrder; 226 227 public ThreadComparator(String threadSortOrder) { 228 this.threadSortOrder = threadSortOrder; 229 } 230 231 @Override 232 public int compare(JThreadInfo jt1, JThreadInfo jt2) { 233 ThreadInfo o1 = jt1.getThreadInfo(); 234 ThreadInfo o2 = jt2.getThreadInfo(); 235 if ("cpu".equals(threadSortOrder)) { 236 int result = (int) (jt2.getCpuTime() - jt1.getCpuTime()); 237 if (result == 0) { 238 return compareId(o1, o2); 239 } 240 return result; 241 } 242 else if ("name".equals(threadSortOrder)) { 243 return compareName(o1, o2); 244 } 245 else { 246 // state 247 if (o1.getThreadState().equals(o2.getThreadState())) { 248 return compareName(o1, o2); 249 } 250 else { 251 return (int) threadStateOrdering.get(o1.getThreadState()) 252 - threadStateOrdering.get(o2.getThreadState()); 253 } 254 } 255 } 256 257 private int compareId(ThreadInfo o1, ThreadInfo o2) { 258 Long id1 = o1.getThreadId(); 259 Long id2 = o2.getThreadId(); 260 return id1.compareTo(id2); 261 } 262 263 private int compareName(ThreadInfo o1, ThreadInfo o2) { 264 int result = o1.getThreadName().compareTo(o2.getThreadName()); 265 if (result == 0) { 266 Long id1 = o1.getThreadId(); 267 Long id2 = o2.getThreadId(); 268 return id1.compareTo(id2); 269 } 270 return result; 271 } 272 273 } 274 275}