1 /* 2 * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package sun.management.snmp.jvminstr; 26 27 // java imports 28 // 29 import java.io.Serializable; 30 import java.lang.management.ThreadInfo; 31 import java.lang.management.ManagementFactory; 32 import java.lang.management.ThreadMXBean; 33 34 // jmx imports 35 // 36 import com.sun.jmx.snmp.SnmpStatusException; 37 38 // jdmk imports 39 // 40 import com.sun.jmx.snmp.agent.SnmpMib; 41 import com.sun.jmx.snmp.SnmpOid; 42 import com.sun.jmx.snmp.SnmpDefinitions; 43 import com.sun.jmx.snmp.SnmpOidTable; 44 import com.sun.jmx.snmp.SnmpOidRecord; 45 46 import sun.management.snmp.jvmmib.JvmThreadInstanceEntryMBean; 47 import sun.management.snmp.jvmmib.JVM_MANAGEMENT_MIBOidTable; 48 import sun.management.snmp.util.MibLogger; 49 50 /** 51 * The class is used for implementing the "JvmThreadInstanceEntry" group. 52 */ 53 public class JvmThreadInstanceEntryImpl 54 implements JvmThreadInstanceEntryMBean, Serializable { 55 56 static final long serialVersionUID = 910173589985461347L; 57 58 public final static class ThreadStateMap { 59 public final static class Byte0 { 60 public final static byte inNative = (byte)0x80; // bit 1 61 public final static byte suspended = (byte)0x40; // bit 2 62 public final static byte newThread = (byte)0x20; // bit 3 63 public final static byte runnable = (byte)0x10; // bit 4 64 public final static byte blocked = (byte)0x08; // bit 5 65 public final static byte terminated = (byte)0x04; // bit 6 66 public final static byte waiting = (byte)0x02; // bit 7 67 public final static byte timedWaiting = (byte)0x01; // bit 8 68 } 69 public final static class Byte1 { 70 public final static byte other = (byte)0x80; // bit 9 71 public final static byte reserved10 = (byte)0x40; // bit 10 72 public final static byte reserved11 = (byte)0x20; // bit 11 73 public final static byte reserved12 = (byte)0x10; // bit 12 74 public final static byte reserved13 = (byte)0x08; // bit 13 75 public final static byte reserved14 = (byte)0x04; // bit 14 76 public final static byte reserved15 = (byte)0x02; // bit 15 77 public final static byte reserved16 = (byte)0x01; // bit 16 78 } 79 80 public final static byte mask0 = (byte)0x3F; 81 public final static byte mask1 = (byte)0x80; 82 setBit(byte[] bitmap, int index, byte state)83 private static void setBit(byte[] bitmap, int index, byte state) { 84 bitmap[index] = (byte) (bitmap[index] | state); 85 } setNative(byte[] bitmap)86 public static void setNative(byte[] bitmap) { 87 setBit(bitmap,0,Byte0.inNative); 88 } setSuspended(byte[] bitmap)89 public static void setSuspended(byte[] bitmap) { 90 setBit(bitmap,0,Byte0.suspended); 91 } setState(byte[] bitmap, Thread.State state)92 public static void setState(byte[] bitmap, Thread.State state) { 93 switch(state) { 94 case BLOCKED: 95 setBit(bitmap,0,Byte0.blocked); 96 return; 97 case NEW: 98 setBit(bitmap,0,Byte0.newThread); 99 return; 100 case RUNNABLE: 101 setBit(bitmap,0,Byte0.runnable); 102 return; 103 case TERMINATED: 104 setBit(bitmap,0,Byte0.terminated); 105 return; 106 case TIMED_WAITING: 107 setBit(bitmap,0,Byte0.timedWaiting); 108 return; 109 case WAITING: 110 setBit(bitmap,0,Byte0.waiting); 111 return; 112 } 113 } 114 checkOther(byte[] bitmap)115 public static void checkOther(byte[] bitmap) { 116 if (((bitmap[0]&mask0)==(byte)0x00) && 117 ((bitmap[1]&mask1)==(byte)0x00)) 118 setBit(bitmap,1,Byte1.other); 119 } 120 getState(ThreadInfo info)121 public static Byte[] getState(ThreadInfo info) { 122 byte[] bitmap = new byte[] {(byte)0x00, (byte)0x00}; 123 try { 124 final Thread.State state = info.getThreadState(); 125 final boolean inNative = info.isInNative(); 126 final boolean suspended = info.isSuspended(); 127 log.debug("getJvmThreadInstState", 128 "[State=" + state + 129 ",isInNative=" + inNative + 130 ",isSuspended=" + suspended + "]"); 131 setState(bitmap,state); 132 if (inNative) setNative(bitmap); 133 if (suspended) setSuspended(bitmap); 134 checkOther(bitmap); 135 } catch (RuntimeException r) { 136 bitmap[0]=(byte)0x00; 137 bitmap[1]=Byte1.other; 138 log.trace("getJvmThreadInstState", 139 "Unexpected exception: " + r); 140 log.debug("getJvmThreadInstState",r); 141 } 142 Byte[] result = { new Byte(bitmap[0]), new Byte(bitmap[1]) }; 143 return result; 144 } 145 } 146 147 private final ThreadInfo info; 148 private final Byte[] index; 149 150 /** 151 * Constructor for the "JvmThreadInstanceEntry" group. 152 */ JvmThreadInstanceEntryImpl(ThreadInfo info, Byte[] index)153 public JvmThreadInstanceEntryImpl(ThreadInfo info, 154 Byte[] index) { 155 this.info = info; 156 this.index = index; 157 } 158 159 160 private static String jvmThreadInstIndexOid = null; getJvmThreadInstIndexOid()161 public static String getJvmThreadInstIndexOid() 162 throws SnmpStatusException { 163 if (jvmThreadInstIndexOid == null) { 164 final SnmpOidTable table = new JVM_MANAGEMENT_MIBOidTable(); 165 final SnmpOidRecord record = 166 table.resolveVarName("jvmThreadInstIndex"); 167 jvmThreadInstIndexOid = record.getOid(); 168 } 169 return jvmThreadInstIndexOid; 170 } 171 172 173 174 /** 175 * Getter for the "JvmThreadInstLockedOwnerId" variable. 176 */ getJvmThreadInstLockOwnerPtr()177 public String getJvmThreadInstLockOwnerPtr() throws SnmpStatusException { 178 long id = info.getLockOwnerId(); 179 180 if(id == -1) 181 return new String("0.0"); 182 183 SnmpOid oid = JvmThreadInstanceTableMetaImpl.makeOid(id); 184 185 return getJvmThreadInstIndexOid() + "." + oid.toString(); 186 } 187 validDisplayStringTC(String str)188 private String validDisplayStringTC(String str) { 189 return JVM_MANAGEMENT_MIB_IMPL.validDisplayStringTC(str); 190 } 191 validJavaObjectNameTC(String str)192 private String validJavaObjectNameTC(String str) { 193 return JVM_MANAGEMENT_MIB_IMPL.validJavaObjectNameTC(str); 194 } 195 validPathElementTC(String str)196 private String validPathElementTC(String str) { 197 return JVM_MANAGEMENT_MIB_IMPL.validPathElementTC(str); 198 } 199 200 /** 201 * Getter for the "JvmThreadInstLockName" variable. 202 */ getJvmThreadInstLockName()203 public String getJvmThreadInstLockName() throws SnmpStatusException { 204 return validJavaObjectNameTC(info.getLockName()); 205 } 206 207 /** 208 * Getter for the "JvmThreadInstName" variable. 209 */ getJvmThreadInstName()210 public String getJvmThreadInstName() throws SnmpStatusException { 211 return validJavaObjectNameTC(info.getThreadName()); 212 } 213 214 /** 215 * Getter for the "JvmThreadInstCpuTimeNs" variable. 216 */ getJvmThreadInstCpuTimeNs()217 public Long getJvmThreadInstCpuTimeNs() throws SnmpStatusException { 218 long l = 0; 219 final ThreadMXBean tmb = JvmThreadingImpl.getThreadMXBean(); 220 221 try { 222 if (tmb.isThreadCpuTimeSupported()) { 223 l = tmb.getThreadCpuTime(info.getThreadId()); 224 log.debug("getJvmThreadInstCpuTimeNs", "Cpu time ns : " + l); 225 226 //Cpu time measurement is disabled or the id is not valid. 227 if(l == -1) l = 0; 228 } 229 } catch (UnsatisfiedLinkError e) { 230 // XXX Revisit: catch TO BE EVENTUALLY REMOVED 231 log.debug("getJvmThreadInstCpuTimeNs", 232 "Operation not supported: " + e); 233 } 234 return new Long(l); 235 } 236 237 /** 238 * Getter for the "JvmThreadInstBlockTimeMs" variable. 239 */ getJvmThreadInstBlockTimeMs()240 public Long getJvmThreadInstBlockTimeMs() throws SnmpStatusException { 241 long l = 0; 242 243 final ThreadMXBean tmb = JvmThreadingImpl.getThreadMXBean(); 244 245 if (tmb.isThreadContentionMonitoringSupported()) { 246 l = info.getBlockedTime(); 247 248 //Monitoring is disabled 249 if(l == -1) l = 0; 250 } 251 return new Long(l); 252 } 253 254 /** 255 * Getter for the "JvmThreadInstBlockCount" variable. 256 */ getJvmThreadInstBlockCount()257 public Long getJvmThreadInstBlockCount() throws SnmpStatusException { 258 return new Long(info.getBlockedCount()); 259 } 260 261 /** 262 * Getter for the "JvmThreadInstWaitTimeMs" variable. 263 */ getJvmThreadInstWaitTimeMs()264 public Long getJvmThreadInstWaitTimeMs() throws SnmpStatusException { 265 long l = 0; 266 267 final ThreadMXBean tmb = JvmThreadingImpl.getThreadMXBean(); 268 269 if (tmb.isThreadContentionMonitoringSupported()) { 270 l = info.getWaitedTime(); 271 272 //Monitoring is disabled 273 if(l == -1) l = 0; 274 } 275 return new Long(l); 276 } 277 278 /** 279 * Getter for the "JvmThreadInstWaitCount" variable. 280 */ getJvmThreadInstWaitCount()281 public Long getJvmThreadInstWaitCount() throws SnmpStatusException { 282 return new Long(info.getWaitedCount()); 283 } 284 285 /** 286 * Getter for the "JvmThreadInstState" variable. 287 */ getJvmThreadInstState()288 public Byte[] getJvmThreadInstState() 289 throws SnmpStatusException { 290 return ThreadStateMap.getState(info); 291 } 292 293 /** 294 * Getter for the "JvmThreadInstId" variable. 295 */ getJvmThreadInstId()296 public Long getJvmThreadInstId() throws SnmpStatusException { 297 return new Long(info.getThreadId()); 298 } 299 300 /** 301 * Getter for the "JvmThreadInstIndex" variable. 302 */ getJvmThreadInstIndex()303 public Byte[] getJvmThreadInstIndex() throws SnmpStatusException { 304 return index; 305 } 306 307 /** 308 * Getter for the "JvmThreadInstStackTrace" variable. 309 */ getJvmThreadInstStackTrace()310 private String getJvmThreadInstStackTrace() throws SnmpStatusException { 311 StackTraceElement[] stackTrace = info.getStackTrace(); 312 //We append the stack trace in a buffer 313 // XXX Revisit: should check isDebugOn() 314 StringBuffer b = new StringBuffer(); 315 final int stackSize = stackTrace.length; 316 log.debug("getJvmThreadInstStackTrace", "Stack size : " + stackSize); 317 for(int i = 0; i < stackSize; i++) { 318 log.debug("getJvmThreadInstStackTrace", "Append " + 319 stackTrace[i].toString()); 320 b.append(stackTrace[i].toString()); 321 //Append \n at the end of each line except the last one 322 if(i < stackSize) 323 b.append("\n"); 324 } 325 //The stack trace is truncated if its size exceeds 255. 326 return validPathElementTC(b.toString()); 327 } 328 static final MibLogger log = 329 new MibLogger(JvmThreadInstanceEntryImpl.class); 330 } 331