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