/*
* This file is part of the Jikes RVM project (http://jikesrvm.org).
*
* This file is licensed to You under the Eclipse Public License (EPL);
* You may not use this file except in compliance with the License. You
* may obtain a copy of the License at
*
* http://www.opensource.org/licenses/eclipse-1.0.php
*
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership.
*/
package gnu.java.lang.management;
import java.lang.management.LockInfo;
import java.lang.management.MonitorInfo;
import java.lang.management.ThreadInfo;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import org.jikesrvm.scheduler.JMXSupport;
import org.jikesrvm.scheduler.RVMThread;
import org.jikesrvm.util.UnimplementedError;
final class VMThreadMXBeanImpl {
/**
* Returns the ids of deadlocked threads occurring due
* to either monitor or ownable synchronizer ownership.
* Only called if ownable synchronizer monitoring is
* supported.
*
* @return an array of thread identifiers.
*/
static long[] findDeadlockedThreads() {
throw new UnimplementedError();
}
/**
* Returns the ids of deadlocked threads occurring due
* to monitor ownership.
*
* @return an array of thread identifiers.
*/
static long[] findMonitorDeadlockedThreads() {
throw new UnimplementedError();
}
/**
* Returns the identifiers of all live threads.
*
* @return an array of thread identifiers.
*/
static long[] getAllThreadIds() {
return JMXSupport.getAllLiveThreadIds();
}
/**
* Returns the number of nanoseconds of CPU time
* the current thread has used, if supported.
*
* @return the number of nanoseconds.
*/
static long getCurrentThreadCpuTime() {
return getThreadCpuTime(getIDForCurrentThread());
}
private static long getIDForCurrentThread() {
return RVMThread.getCurrentThread().getJavaLangThread().getId();
}
/**
* Returns the number of nanoseconds of user time
* the current thread has used, if supported.
*
* @return the number of nanoseconds.
*/
static long getCurrentThreadUserTime() {
return getThreadUserTime(getIDForCurrentThread());
}
/**
* Returns the number of live daemon threads.
*
* @return the number of live daemon threads.
*/
static int getDaemonThreadCount() {
return JMXSupport.getLiveDaemonCount();
}
/**
* Fills out the information on ownable synchronizers
* in the given {@link java.lang.management.ThreadInfo}
* object if supported.
*
* @param info the object to fill in.
*/
static void getLockInfo(ThreadInfo info) {
throw new UnimplementedError();
}
/**
* Fills out the information on monitor usage
* in the given {@link java.lang.management.ThreadInfo}
* object if supported.
*
* @param info the object to fill in.
*/
static void getMonitorInfo(ThreadInfo info) {
throw new UnimplementedError();
}
/**
* Returns the current peak number of live threads.
*
* @return the current peak.
*/
static int getPeakThreadCount() {
return JMXSupport.getPeakThreadCount();
}
/**
* Returns the current number of live threads.
*
* @return the current number of live threads.
*/
static int getThreadCount() {
return JMXSupport.getLiveThreadCount();
}
/**
* Returns the number of nanoseconds of CPU time
* the given thread has used, if supported.
*
* @param id the id of the thread to probe.
* @return the number of nanoseconds.
*/
static long getThreadCpuTime(long id) {
throw new UnimplementedError();
}
/**
* Returns a {@link java.lang.management.ThreadInfo}
* object for the given thread id with a stack trace to
* the given depth (0 for empty, Integer.MAX_VALUE for
* full).
*
* @param id the id of the thread whose info should be returned.
* @param maxDepth the depth of the stack trace.
* @return a {@link java.lang.management.ThreadInfo} instance.
*/
static ThreadInfo getThreadInfoForId(long id, int maxDepth) {
Thread thread = getThreadForId(id);
Constructor<ThreadInfo> cons = null;
try {
// ensure class is at least resolved
Class.forName("java.lang.management.ThreadInfo");
cons = ThreadInfo.class.getDeclaredConstructor(Long.TYPE, String.class,
Thread.State.class, Long.TYPE,
Long.TYPE, String.class,
Long.TYPE, String.class,
Long.TYPE, Long.TYPE,
Boolean.TYPE,Boolean.TYPE,
StackTraceElement[].class, MonitorInfo[].class,
LockInfo[].class);
cons.setAccessible(true);
RVMThread rvmThread = JikesRVMSupport.getThread(thread);
long blockedCount = 0; // TODO number of times blocked for Java monitors
long blockedTime = 0; // TODO total time blocked for Java monitors
long waitingCount = JMXSupport.getWaitingCount(rvmThread);
long waitingTime = JMXSupport.getWaitingTime(rvmThread);
boolean inNative = JMXSupport.isInNative(rvmThread);
boolean suspended = JMXSupport.isSuspended(rvmThread);
StackTraceElement[] stackTrace;
if (maxDepth == 0) {
stackTrace = null;
} else {
stackTrace = JMXSupport.getStackTraceForThread(rvmThread);
int newMax = Math.min(stackTrace.length, maxDepth);
StackTraceElement[] reducedStackTrace = new StackTraceElement[newMax];
int srcPos = stackTrace.length - newMax;
System.arraycopy(stackTrace, srcPos, reducedStackTrace,
0, newMax);
stackTrace = reducedStackTrace;
}
MonitorInfo[] emptyMonitorInfo = new MonitorInfo[0];
LockInfo[] emptyLockInfo = new LockInfo[0];
return cons.newInstance(id, thread.getName(), thread.getState(),
blockedCount, blockedTime,
null, -1, null, waitingCount,
waitingTime,
inNative,
suspended, stackTrace, emptyMonitorInfo, emptyLockInfo);
} catch (NoSuchMethodException e) {
throw (Error) new InternalError("Couldn't get ThreadInfo constructor").initCause(e);
} catch (InstantiationException e) {
throw (Error) new InternalError("Couldn't create ThreadInfo").initCause(e);
} catch (IllegalAccessException e) {
throw (Error) new InternalError("Couldn't access ThreadInfo").initCause(e);
} catch (InvocationTargetException e) {
throw (Error) new InternalError("ThreadInfo's constructor threw an exception").initCause(e);
} catch (ClassNotFoundException e) {
throw (Error) new InternalError("Problem resolving ThreadInfo").initCause(e);
}
}
/**
* Returns the Thread instance for the given
* thread id.
*
* @param id the id of the thread to find.
* @return the Thread.
*/
private static Thread getThreadForId(long id) {
return JMXSupport.getThreadForId(id);
}
/**
* Returns the number of nanoseconds of user time
* the given thread has used, if supported.
*
* @param id the id of the thread to probe.
* @return the number of nanoseconds.
*/
static long getThreadUserTime(long id) {
throw new UnimplementedError();
}
/**
* Returns the number of threads started.
*
* @return the number of started threads.
*/
static long getTotalStartedThreadCount() {
return JMXSupport.getStartedThreadCount();
}
/**
* Resets the peak thread count.
*/
static void resetPeakThreadCount() {
JMXSupport.resetPeakThreadCount();
}
}