blob: 4410a7c1be88b86f79ad4f437524f8286961ff91 [file] [log] [blame]
/*
* Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.management.snmp.jvminstr;
// java imports
//
import java.io.Serializable;
import java.lang.management.ThreadInfo;
import java.lang.management.ManagementFactory;
import java.lang.management.ThreadMXBean;
// jmx imports
//
import com.sun.jmx.snmp.SnmpStatusException;
// jdmk imports
//
import com.sun.jmx.snmp.agent.SnmpMib;
import com.sun.jmx.snmp.SnmpOid;
import com.sun.jmx.snmp.SnmpDefinitions;
import com.sun.jmx.snmp.SnmpOidTable;
import com.sun.jmx.snmp.SnmpOidRecord;
import sun.management.snmp.jvmmib.JvmThreadInstanceEntryMBean;
import sun.management.snmp.jvmmib.JVM_MANAGEMENT_MIBOidTable;
import sun.management.snmp.util.MibLogger;
/**
* The class is used for implementing the "JvmThreadInstanceEntry" group.
*/
public class JvmThreadInstanceEntryImpl
implements JvmThreadInstanceEntryMBean, Serializable {
public final static class ThreadStateMap {
public final static class Byte0 {
public final static byte inNative = (byte)0x80; // bit 1
public final static byte suspended = (byte)0x40; // bit 2
public final static byte newThread = (byte)0x20; // bit 3
public final static byte runnable = (byte)0x10; // bit 4
public final static byte blocked = (byte)0x08; // bit 5
public final static byte terminated = (byte)0x04; // bit 6
public final static byte waiting = (byte)0x02; // bit 7
public final static byte timedWaiting = (byte)0x01; // bit 8
}
public final static class Byte1 {
public final static byte other = (byte)0x80; // bit 9
public final static byte reserved10 = (byte)0x40; // bit 10
public final static byte reserved11 = (byte)0x20; // bit 11
public final static byte reserved12 = (byte)0x10; // bit 12
public final static byte reserved13 = (byte)0x08; // bit 13
public final static byte reserved14 = (byte)0x04; // bit 14
public final static byte reserved15 = (byte)0x02; // bit 15
public final static byte reserved16 = (byte)0x01; // bit 16
}
public final static byte mask0 = (byte)0x3F;
public final static byte mask1 = (byte)0x80;
private static void setBit(byte[] bitmap, int index, byte state) {
bitmap[index] = (byte) (bitmap[index] | state);
}
public static void setNative(byte[] bitmap) {
setBit(bitmap,0,Byte0.inNative);
}
public static void setSuspended(byte[] bitmap) {
setBit(bitmap,0,Byte0.suspended);
}
public static void setState(byte[] bitmap, Thread.State state) {
switch(state) {
case BLOCKED:
setBit(bitmap,0,Byte0.blocked);
return;
case NEW:
setBit(bitmap,0,Byte0.newThread);
return;
case RUNNABLE:
setBit(bitmap,0,Byte0.runnable);
return;
case TERMINATED:
setBit(bitmap,0,Byte0.terminated);
return;
case TIMED_WAITING:
setBit(bitmap,0,Byte0.timedWaiting);
return;
case WAITING:
setBit(bitmap,0,Byte0.waiting);
return;
}
}
public static void checkOther(byte[] bitmap) {
if (((bitmap[0]&mask0)==(byte)0x00) &&
((bitmap[1]&mask1)==(byte)0x00))
setBit(bitmap,1,Byte1.other);
}
public static Byte[] getState(ThreadInfo info) {
byte[] bitmap = new byte[] {(byte)0x00, (byte)0x00};
try {
final Thread.State state = info.getThreadState();
final boolean inNative = info.isInNative();
final boolean suspended = info.isSuspended();
log.debug("getJvmThreadInstState",
"[State=" + state +
",isInNative=" + inNative +
",isSuspended=" + suspended + "]");
setState(bitmap,state);
if (inNative) setNative(bitmap);
if (suspended) setSuspended(bitmap);
checkOther(bitmap);
} catch (RuntimeException r) {
bitmap[0]=(byte)0x00;
bitmap[1]=Byte1.other;
log.trace("getJvmThreadInstState",
"Unexpected exception: " + r);
log.debug("getJvmThreadInstState",r);
}
Byte[] result = { new Byte(bitmap[0]), new Byte(bitmap[1]) };
return result;
}
}
private final ThreadInfo info;
private final Byte[] index;
/**
* Constructor for the "JvmThreadInstanceEntry" group.
*/
public JvmThreadInstanceEntryImpl(ThreadInfo info,
Byte[] index) {
this.info = info;
this.index = index;
}
private static String jvmThreadInstIndexOid = null;
public static String getJvmThreadInstIndexOid()
throws SnmpStatusException {
if (jvmThreadInstIndexOid == null) {
final SnmpOidTable table = new JVM_MANAGEMENT_MIBOidTable();
final SnmpOidRecord record =
table.resolveVarName("jvmThreadInstIndex");
jvmThreadInstIndexOid = record.getOid();
}
return jvmThreadInstIndexOid;
}
/**
* Getter for the "JvmThreadInstLockedOwnerId" variable.
*/
public String getJvmThreadInstLockOwnerPtr() throws SnmpStatusException {
long id = info.getLockOwnerId();
if(id == -1)
return new String("0.0");
SnmpOid oid = JvmThreadInstanceTableMetaImpl.makeOid(id);
return getJvmThreadInstIndexOid() + "." + oid.toString();
}
private String validDisplayStringTC(String str) {
return JVM_MANAGEMENT_MIB_IMPL.validDisplayStringTC(str);
}
private String validJavaObjectNameTC(String str) {
return JVM_MANAGEMENT_MIB_IMPL.validJavaObjectNameTC(str);
}
private String validPathElementTC(String str) {
return JVM_MANAGEMENT_MIB_IMPL.validPathElementTC(str);
}
/**
* Getter for the "JvmThreadInstLockName" variable.
*/
public String getJvmThreadInstLockName() throws SnmpStatusException {
return validJavaObjectNameTC(info.getLockName());
}
/**
* Getter for the "JvmThreadInstName" variable.
*/
public String getJvmThreadInstName() throws SnmpStatusException {
return validJavaObjectNameTC(info.getThreadName());
}
/**
* Getter for the "JvmThreadInstCpuTimeNs" variable.
*/
public Long getJvmThreadInstCpuTimeNs() throws SnmpStatusException {
long l = 0;
final ThreadMXBean tmb = JvmThreadingImpl.getThreadMXBean();
try {
if (tmb.isThreadCpuTimeSupported()) {
l = tmb.getThreadCpuTime(info.getThreadId());
log.debug("getJvmThreadInstCpuTimeNs", "Cpu time ns : " + l);
//Cpu time measurement is disabled or the id is not valid.
if(l == -1) l = 0;
}
} catch (UnsatisfiedLinkError e) {
// XXX Revisit: catch TO BE EVENTUALLY REMOVED
log.debug("getJvmThreadInstCpuTimeNs",
"Operation not supported: " + e);
}
return new Long(l);
}
/**
* Getter for the "JvmThreadInstBlockTimeMs" variable.
*/
public Long getJvmThreadInstBlockTimeMs() throws SnmpStatusException {
long l = 0;
final ThreadMXBean tmb = JvmThreadingImpl.getThreadMXBean();
if (tmb.isThreadContentionMonitoringSupported()) {
l = info.getBlockedTime();
//Monitoring is disabled
if(l == -1) l = 0;
}
return new Long(l);
}
/**
* Getter for the "JvmThreadInstBlockCount" variable.
*/
public Long getJvmThreadInstBlockCount() throws SnmpStatusException {
return new Long(info.getBlockedCount());
}
/**
* Getter for the "JvmThreadInstWaitTimeMs" variable.
*/
public Long getJvmThreadInstWaitTimeMs() throws SnmpStatusException {
long l = 0;
final ThreadMXBean tmb = JvmThreadingImpl.getThreadMXBean();
if (tmb.isThreadContentionMonitoringSupported()) {
l = info.getWaitedTime();
//Monitoring is disabled
if(l == -1) l = 0;
}
return new Long(l);
}
/**
* Getter for the "JvmThreadInstWaitCount" variable.
*/
public Long getJvmThreadInstWaitCount() throws SnmpStatusException {
return new Long(info.getWaitedCount());
}
/**
* Getter for the "JvmThreadInstState" variable.
*/
public Byte[] getJvmThreadInstState()
throws SnmpStatusException {
return ThreadStateMap.getState(info);
}
/**
* Getter for the "JvmThreadInstId" variable.
*/
public Long getJvmThreadInstId() throws SnmpStatusException {
return new Long(info.getThreadId());
}
/**
* Getter for the "JvmThreadInstIndex" variable.
*/
public Byte[] getJvmThreadInstIndex() throws SnmpStatusException {
return index;
}
/**
* Getter for the "JvmThreadInstStackTrace" variable.
*/
private String getJvmThreadInstStackTrace() throws SnmpStatusException {
StackTraceElement[] stackTrace = info.getStackTrace();
//We append the stack trace in a buffer
// XXX Revisit: should check isDebugOn()
StringBuffer b = new StringBuffer();
final int stackSize = stackTrace.length;
log.debug("getJvmThreadInstStackTrace", "Stack size : " + stackSize);
for(int i = 0; i < stackSize; i++) {
log.debug("getJvmThreadInstStackTrace", "Append " +
stackTrace[i].toString());
b.append(stackTrace[i].toString());
//Append \n at the end of each line except the last one
if(i < stackSize)
b.append("\n");
}
//The stack trace is truncated if its size exceeds 255.
return validPathElementTC(b.toString());
}
static final MibLogger log =
new MibLogger(JvmThreadInstanceEntryImpl.class);
}