1/* 2 * Copyright (c) 2004, 2009, 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. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25package sun.jvm.hotspot.utilities.soql; 26 27import java.util.*; 28import sun.jvm.hotspot.debugger.*; 29import sun.jvm.hotspot.oops.*; 30import sun.jvm.hotspot.runtime.*; 31 32/** 33 * Wraps a JavaThread instance in the target VM. 34 */ 35public class JSJavaThread extends JSJavaInstance { 36 public JSJavaThread(Instance threadOop, JSJavaFactory fac) { 37 super(threadOop, fac); 38 // JavaThread retrieved from java.lang.Thread instance may be null. 39 // This is the case for threads not-started and for zombies. Wherever 40 // appropriate, check for null instead of resulting in NullPointerException. 41 this.jthread = OopUtilities.threadOopGetJavaThread(threadOop); 42 } 43 44 public JSJavaThread(JavaThread jt, JSJavaFactory fac) { 45 super((Instance) jt.getThreadObj(), fac); 46 this.jthread = jt; 47 } 48 49 public String toString() { 50 String name = getName(); 51 StringBuffer buf = new StringBuffer(); 52 buf.append("Thread (address="); 53 buf.append(getOop().getHandle()); 54 buf.append(", name="); 55 if (name != null) { 56 buf.append(name); 57 } else { 58 buf.append("<unnamed>"); 59 } 60 buf.append(')'); 61 return buf.toString(); 62 } 63 64 protected Object getFieldValue(String name) { 65 if (name.equals("name")) { 66 return getName(); 67 } else if (name.equals("frames")) { 68 return getFrames(); 69 } else if (name.equals("monitors")) { 70 return getOwnedMonitors(); 71 } else { 72 return super.getFieldValue(name); 73 } 74 } 75 76 protected String[] getFieldNames() { 77 String[] flds = super.getFieldNames(); 78 String[] res = new String[flds.length + 2]; 79 System.arraycopy(flds, 0, res, 0, flds.length); 80 res[flds.length] = "frames"; 81 res[flds.length + 1] = "monitors"; 82 return res; 83 } 84 85 protected boolean hasField(String name) { 86 if (name.equals("frames") || name.equals("monitors")) { 87 return true; 88 } else { 89 return super.hasField(name); 90 } 91 } 92 93 //-- Internals only below this point 94 private String getName() { 95 return OopUtilities.threadOopGetName(getOop()); 96 } 97 98 private synchronized JSList getFrames() { 99 if (framesCache == null) { 100 final List list = new ArrayList(0); 101 if (jthread != null) { 102 JavaVFrame jvf = jthread.getLastJavaVFrameDbg(); 103 while (jvf != null) { 104 list.add(jvf); 105 jvf = jvf.javaSender(); 106 } 107 } 108 framesCache = factory.newJSList(list); 109 } 110 return framesCache; 111 } 112 113 private synchronized JSList getOwnedMonitors() { 114 if (monitorsCache == null) { 115 final List ownedMonitors = new ArrayList(0); 116 if (jthread != null) { 117 List lockedObjects = new ArrayList(); // List<OopHandle> 118 119 ObjectMonitor waitingMonitor = jthread.getCurrentWaitingMonitor(); 120 OopHandle waitingObj = null; 121 if (waitingMonitor != null) { 122 // save object of current wait() call (if any) for later comparison 123 waitingObj = waitingMonitor.object(); 124 } 125 126 ObjectMonitor pendingMonitor = jthread.getCurrentPendingMonitor(); 127 OopHandle pendingObj = null; 128 if (pendingMonitor != null) { 129 // save object of current enter() call (if any) for later comparison 130 pendingObj = pendingMonitor.object(); 131 } 132 133 JavaVFrame frame = jthread.getLastJavaVFrameDbg(); 134 while (frame != null) { 135 List frameMonitors = frame.getMonitors(); // List<MonitorInfo> 136 for (Iterator miItr = frameMonitors.iterator(); miItr.hasNext(); ) { 137 MonitorInfo mi = (MonitorInfo) miItr.next(); 138 139 if (mi.eliminated() && frame.isCompiledFrame()) { 140 continue; // skip eliminated monitor 141 } 142 OopHandle obj = mi.owner(); 143 if (obj == null) { 144 // this monitor doesn't have an owning object so skip it 145 continue; 146 } 147 148 if (obj.equals(waitingObj)) { 149 // the thread is waiting on this monitor so it isn't really owned 150 continue; 151 } 152 153 if (obj.equals(pendingObj)) { 154 // the thread is pending on this monitor so it isn't really owned 155 continue; 156 } 157 158 boolean found = false; 159 for (Iterator loItr = lockedObjects.iterator(); loItr.hasNext(); ) { 160 // check for recursive locks 161 if (obj.equals(loItr.next())) { 162 found = true; 163 break; 164 } 165 } 166 if (found) { 167 // already have this object so don't include it 168 continue; 169 } 170 // add the owning object to our list 171 lockedObjects.add(obj); 172 } 173 frame = (JavaVFrame) frame.javaSender(); 174 } 175 176 // now convert List<OopHandle> to List<Oop> 177 ObjectHeap heap = VM.getVM().getObjectHeap(); 178 for (Iterator loItr = lockedObjects.iterator(); loItr.hasNext(); ) { 179 ownedMonitors.add(heap.newOop((OopHandle)loItr.next())); 180 } 181 } 182 monitorsCache = factory.newJSList(ownedMonitors); 183 } 184 return monitorsCache; 185 } 186 187 private JavaThread jthread; 188 private JSList framesCache; 189 private JSList monitorsCache; 190} 191