001/* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013package gnu.java.lang.management; 014 015import java.lang.management.LockInfo; 016import java.lang.management.MonitorInfo; 017import java.lang.management.ThreadInfo; 018import java.lang.reflect.Constructor; 019import java.lang.reflect.InvocationTargetException; 020 021import org.jikesrvm.scheduler.JMXSupport; 022import org.jikesrvm.scheduler.RVMThread; 023import org.jikesrvm.util.UnimplementedError; 024 025final class VMThreadMXBeanImpl { 026 027 /** 028 * Returns the ids of deadlocked threads occurring due 029 * to either monitor or ownable synchronizer ownership. 030 * Only called if ownable synchronizer monitoring is 031 * supported. 032 * 033 * @return an array of thread identifiers. 034 */ 035 static long[] findDeadlockedThreads() { 036 throw new UnimplementedError(); 037 } 038 039 /** 040 * Returns the ids of deadlocked threads occurring due 041 * to monitor ownership. 042 * 043 * @return an array of thread identifiers. 044 */ 045 static long[] findMonitorDeadlockedThreads() { 046 throw new UnimplementedError(); 047 } 048 049 /** 050 * Returns the identifiers of all live threads. 051 * 052 * @return an array of thread identifiers. 053 */ 054 static long[] getAllThreadIds() { 055 return JMXSupport.getAllLiveThreadIds(); 056 } 057 058 /** 059 * Returns the number of nanoseconds of CPU time 060 * the current thread has used, if supported. 061 * 062 * @return the number of nanoseconds. 063 */ 064 static long getCurrentThreadCpuTime() { 065 return getThreadCpuTime(getIDForCurrentThread()); 066 } 067 068 private static long getIDForCurrentThread() { 069 return RVMThread.getCurrentThread().getJavaLangThread().getId(); 070 } 071 072 /** 073 * Returns the number of nanoseconds of user time 074 * the current thread has used, if supported. 075 * 076 * @return the number of nanoseconds. 077 */ 078 static long getCurrentThreadUserTime() { 079 return getThreadUserTime(getIDForCurrentThread()); 080 } 081 082 /** 083 * Returns the number of live daemon threads. 084 * 085 * @return the number of live daemon threads. 086 */ 087 static int getDaemonThreadCount() { 088 return JMXSupport.getLiveDaemonCount(); 089 } 090 091 /** 092 * Fills out the information on ownable synchronizers 093 * in the given {@link java.lang.management.ThreadInfo} 094 * object if supported. 095 * 096 * @param info the object to fill in. 097 */ 098 static void getLockInfo(ThreadInfo info) { 099 throw new UnimplementedError(); 100 } 101 102 /** 103 * Fills out the information on monitor usage 104 * in the given {@link java.lang.management.ThreadInfo} 105 * object if supported. 106 * 107 * @param info the object to fill in. 108 */ 109 static void getMonitorInfo(ThreadInfo info) { 110 throw new UnimplementedError(); 111 } 112 113 /** 114 * Returns the current peak number of live threads. 115 * 116 * @return the current peak. 117 */ 118 static int getPeakThreadCount() { 119 return JMXSupport.getPeakThreadCount(); 120 } 121 122 /** 123 * Returns the current number of live threads. 124 * 125 * @return the current number of live threads. 126 */ 127 static int getThreadCount() { 128 return JMXSupport.getLiveThreadCount(); 129 } 130 131 /** 132 * Returns the number of nanoseconds of CPU time 133 * the given thread has used, if supported. 134 * 135 * @param id the id of the thread to probe. 136 * @return the number of nanoseconds. 137 */ 138 static long getThreadCpuTime(long id) { 139 throw new UnimplementedError(); 140 } 141 142 /** 143 * Returns a {@link java.lang.management.ThreadInfo} 144 * object for the given thread id with a stack trace to 145 * the given depth (0 for empty, Integer.MAX_VALUE for 146 * full). 147 * 148 * @param id the id of the thread whose info should be returned. 149 * @param maxDepth the depth of the stack trace. 150 * @return a {@link java.lang.management.ThreadInfo} instance. 151 */ 152 static ThreadInfo getThreadInfoForId(long id, int maxDepth) { 153 Thread thread = getThreadForId(id); 154 Constructor<ThreadInfo> cons = null; 155 try { 156 // ensure class is at least resolved 157 Class.forName("java.lang.management.ThreadInfo"); 158 159 cons = ThreadInfo.class.getDeclaredConstructor(Long.TYPE, String.class, 160 Thread.State.class, Long.TYPE, 161 Long.TYPE, String.class, 162 Long.TYPE, String.class, 163 Long.TYPE, Long.TYPE, 164 Boolean.TYPE,Boolean.TYPE, 165 StackTraceElement[].class, MonitorInfo[].class, 166 LockInfo[].class); 167 168 169 cons.setAccessible(true); 170 RVMThread rvmThread = JikesRVMSupport.getThread(thread); 171 long blockedCount = 0; // TODO number of times blocked for Java monitors 172 long blockedTime = 0; // TODO total time blocked for Java monitors 173 long waitingCount = JMXSupport.getWaitingCount(rvmThread); 174 long waitingTime = JMXSupport.getWaitingTime(rvmThread); 175 boolean inNative = JMXSupport.isInNative(rvmThread); 176 boolean suspended = JMXSupport.isSuspended(rvmThread); 177 178 StackTraceElement[] stackTrace; 179 if (maxDepth == 0) { 180 stackTrace = null; 181 } else { 182 stackTrace = JMXSupport.getStackTraceForThread(rvmThread); 183 int newMax = Math.min(stackTrace.length, maxDepth); 184 StackTraceElement[] reducedStackTrace = new StackTraceElement[newMax]; 185 int srcPos = stackTrace.length - newMax; 186 System.arraycopy(stackTrace, srcPos, reducedStackTrace, 187 0, newMax); 188 stackTrace = reducedStackTrace; 189 } 190 191 MonitorInfo[] emptyMonitorInfo = new MonitorInfo[0]; 192 LockInfo[] emptyLockInfo = new LockInfo[0]; 193 return cons.newInstance(id, thread.getName(), thread.getState(), 194 blockedCount, blockedTime, 195 null, -1, null, waitingCount, 196 waitingTime, 197 inNative, 198 suspended, stackTrace, emptyMonitorInfo, emptyLockInfo); 199 } catch (NoSuchMethodException e) { 200 throw (Error) new InternalError("Couldn't get ThreadInfo constructor").initCause(e); 201 } catch (InstantiationException e) { 202 throw (Error) new InternalError("Couldn't create ThreadInfo").initCause(e); 203 } catch (IllegalAccessException e) { 204 throw (Error) new InternalError("Couldn't access ThreadInfo").initCause(e); 205 } catch (InvocationTargetException e) { 206 throw (Error) new InternalError("ThreadInfo's constructor threw an exception").initCause(e); 207 } catch (ClassNotFoundException e) { 208 throw (Error) new InternalError("Problem resolving ThreadInfo").initCause(e); 209 } 210 } 211 212 /** 213 * Returns the Thread instance for the given 214 * thread id. 215 * 216 * @param id the id of the thread to find. 217 * @return the Thread. 218 */ 219 private static Thread getThreadForId(long id) { 220 return JMXSupport.getThreadForId(id); 221 } 222 223 /** 224 * Returns the number of nanoseconds of user time 225 * the given thread has used, if supported. 226 * 227 * @param id the id of the thread to probe. 228 * @return the number of nanoseconds. 229 */ 230 static long getThreadUserTime(long id) { 231 throw new UnimplementedError(); 232 } 233 234 /** 235 * Returns the number of threads started. 236 * 237 * @return the number of started threads. 238 */ 239 static long getTotalStartedThreadCount() { 240 return JMXSupport.getStartedThreadCount(); 241 } 242 243 /** 244 * Resets the peak thread count. 245 */ 246 static void resetPeakThreadCount() { 247 JMXSupport.resetPeakThreadCount(); 248 } 249 250}