agent/src/share/classes/sun/jvm/hotspot/runtime/JavaThread.java

Mon, 18 Nov 2019 23:41:06 -0500

author
dholmes
date
Mon, 18 Nov 2019 23:41:06 -0500
changeset 9903
f37c2dd33031
parent 8191
c1679cc87ba0
child 9931
fd44df5e3bc3
permissions
-rw-r--r--

8215355: Object monitor deadlock with no threads holding the monitor (using jemalloc 5.1)
Reviewed-by: rehn, stuefe, dcubed, sspitsyn

duke@435 1 /*
minqi@4750 2 * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
duke@435 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@435 4 *
duke@435 5 * This code is free software; you can redistribute it and/or modify it
duke@435 6 * under the terms of the GNU General Public License version 2 only, as
duke@435 7 * published by the Free Software Foundation.
duke@435 8 *
duke@435 9 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@435 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@435 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@435 12 * version 2 for more details (a copy is included in the LICENSE file that
duke@435 13 * accompanied this code).
duke@435 14 *
duke@435 15 * You should have received a copy of the GNU General Public License version
duke@435 16 * 2 along with this work; if not, write to the Free Software Foundation,
duke@435 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@435 18 *
trims@1907 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1907 20 * or visit www.oracle.com if you need additional information or have any
trims@1907 21 * questions.
duke@435 22 *
duke@435 23 */
duke@435 24
duke@435 25 package sun.jvm.hotspot.runtime;
duke@435 26
duke@435 27 import java.io.*;
duke@435 28 import java.util.*;
duke@435 29 import sun.jvm.hotspot.debugger.*;
duke@435 30 import sun.jvm.hotspot.oops.*;
duke@435 31 import sun.jvm.hotspot.types.*;
duke@435 32 import sun.jvm.hotspot.utilities.*;
duke@435 33
duke@435 34 /** This is an abstract class because there are certain OS- and
duke@435 35 CPU-specific operations (like the setting and getting of the last
duke@435 36 Java frame pointer) which need to be factored out. These
duke@435 37 operations are implemented by, for example,
duke@435 38 SolarisSPARCJavaThread, and the concrete subclasses are
duke@435 39 instantiated by the JavaThreadFactory in the Threads class. */
duke@435 40
duke@435 41 public class JavaThread extends Thread {
duke@435 42 private static final boolean DEBUG = System.getProperty("sun.jvm.hotspot.runtime.JavaThread.DEBUG") != null;
duke@435 43
duke@435 44 private static AddressField nextField;
duke@435 45 private static sun.jvm.hotspot.types.OopField threadObjField;
duke@435 46 private static AddressField anchorField;
duke@435 47 private static AddressField lastJavaSPField;
duke@435 48 private static AddressField lastJavaPCField;
duke@435 49 private static CIntegerField threadStateField;
duke@435 50 private static AddressField osThreadField;
xlu@1137 51 private static AddressField stackBaseField;
xlu@1137 52 private static CIntegerField stackSizeField;
duke@435 53
duke@435 54 private static JavaThreadPDAccess access;
duke@435 55
duke@435 56 // JavaThreadStates read from underlying process
duke@435 57 private static int UNINITIALIZED;
duke@435 58 private static int NEW;
duke@435 59 private static int NEW_TRANS;
duke@435 60 private static int IN_NATIVE;
duke@435 61 private static int IN_NATIVE_TRANS;
duke@435 62 private static int IN_VM;
duke@435 63 private static int IN_VM_TRANS;
duke@435 64 private static int IN_JAVA;
duke@435 65 private static int IN_JAVA_TRANS;
duke@435 66 private static int BLOCKED;
duke@435 67 private static int BLOCKED_TRANS;
duke@435 68
duke@435 69 static {
duke@435 70 VM.registerVMInitializedObserver(new Observer() {
duke@435 71 public void update(Observable o, Object data) {
duke@435 72 initialize(VM.getVM().getTypeDataBase());
duke@435 73 }
duke@435 74 });
duke@435 75 }
duke@435 76
duke@435 77 private static synchronized void initialize(TypeDataBase db) {
duke@435 78 Type type = db.lookupType("JavaThread");
duke@435 79 Type anchorType = db.lookupType("JavaFrameAnchor");
duke@435 80
duke@435 81 nextField = type.getAddressField("_next");
duke@435 82 threadObjField = type.getOopField("_threadObj");
duke@435 83 anchorField = type.getAddressField("_anchor");
duke@435 84 lastJavaSPField = anchorType.getAddressField("_last_Java_sp");
duke@435 85 lastJavaPCField = anchorType.getAddressField("_last_Java_pc");
duke@435 86 threadStateField = type.getCIntegerField("_thread_state");
duke@435 87 osThreadField = type.getAddressField("_osthread");
xlu@1137 88 stackBaseField = type.getAddressField("_stack_base");
xlu@1137 89 stackSizeField = type.getCIntegerField("_stack_size");
duke@435 90
duke@435 91 UNINITIALIZED = db.lookupIntConstant("_thread_uninitialized").intValue();
duke@435 92 NEW = db.lookupIntConstant("_thread_new").intValue();
duke@435 93 NEW_TRANS = db.lookupIntConstant("_thread_new_trans").intValue();
duke@435 94 IN_NATIVE = db.lookupIntConstant("_thread_in_native").intValue();
duke@435 95 IN_NATIVE_TRANS = db.lookupIntConstant("_thread_in_native_trans").intValue();
duke@435 96 IN_VM = db.lookupIntConstant("_thread_in_vm").intValue();
duke@435 97 IN_VM_TRANS = db.lookupIntConstant("_thread_in_vm_trans").intValue();
duke@435 98 IN_JAVA = db.lookupIntConstant("_thread_in_Java").intValue();
duke@435 99 IN_JAVA_TRANS = db.lookupIntConstant("_thread_in_Java_trans").intValue();
duke@435 100 BLOCKED = db.lookupIntConstant("_thread_blocked").intValue();
duke@435 101 BLOCKED_TRANS = db.lookupIntConstant("_thread_blocked_trans").intValue();
duke@435 102 }
duke@435 103
duke@435 104 public JavaThread(Address addr) {
duke@435 105 super(addr);
duke@435 106 }
duke@435 107
duke@435 108 void setThreadPDAccess(JavaThreadPDAccess access) {
duke@435 109 this.access = access;
duke@435 110 }
duke@435 111
duke@435 112 public JavaThread next() {
duke@435 113 Address threadAddr = nextField.getValue(addr);
duke@435 114 if (threadAddr == null) {
duke@435 115 return null;
duke@435 116 }
duke@435 117
duke@435 118 return VM.getVM().getThreads().createJavaThreadWrapper(threadAddr);
duke@435 119 }
duke@435 120
duke@435 121 /** NOTE: for convenience, this differs in definition from the
duke@435 122 underlying VM. Only "pure" JavaThreads return true;
duke@435 123 CompilerThreads and JVMDIDebuggerThreads return false. FIXME:
duke@435 124 consider encapsulating platform-specific functionality in an
duke@435 125 object instead of using inheritance (which is the primary reason
duke@435 126 we can't traverse CompilerThreads, etc; didn't want to have, for
duke@435 127 example, "SolarisSPARCCompilerThread".) */
duke@435 128 public boolean isJavaThread() { return true; }
duke@435 129
duke@435 130 public static AddressField getAnchorField() { return anchorField; }
duke@435 131
duke@435 132 /** Get the last Java stack pointer */
duke@435 133 public Address getLastJavaSP() {
duke@435 134 Address sp = lastJavaSPField.getValue(addr.addOffsetTo(anchorField.getOffset()));
duke@435 135 return sp;
duke@435 136 }
duke@435 137
duke@435 138 public Address getLastJavaPC() {
duke@435 139 Address pc = lastJavaPCField.getValue(addr.addOffsetTo(anchorField.getOffset()));
duke@435 140 return pc;
duke@435 141 }
duke@435 142
duke@435 143 /** Abstract accessor to last Java frame pointer, implemented by
duke@435 144 OS/CPU-specific JavaThread implementation. May return null if
duke@435 145 there is no frame pointer or if it is not necessary on this
duke@435 146 platform. */
duke@435 147 public Address getLastJavaFP(){
duke@435 148 return access.getLastJavaFP(addr);
duke@435 149 }
duke@435 150
duke@435 151 /** Abstract accessor to last Java pc, implemented by
duke@435 152 OS/CPU-specific JavaThread implementation. May return null if
duke@435 153 there is no frame pointer or if it is not necessary on this
duke@435 154 platform. */
duke@435 155
duke@435 156 /*
duke@435 157 public Address getLastJavaPC(){
duke@435 158 return access.getLastJavaPC(addr);
duke@435 159 }
duke@435 160 */
duke@435 161
duke@435 162 // FIXME: not yet implementable
duke@435 163 // public abstract void setLastJavaFP(Address fp);
duke@435 164
duke@435 165 /** A stack pointer older than any java frame stack pointer. Only
duke@435 166 needed on some platforms; for example, see
duke@435 167 thread_solaris_sparc.hpp. */
duke@435 168 public Address getBaseOfStackPointer(){
duke@435 169 return access.getBaseOfStackPointer(addr);
duke@435 170 }
duke@435 171 // FIXME: not yet implementable
duke@435 172 // public abstract void setBaseOfStackPointer(Address fp);
duke@435 173
duke@435 174 /** Tells whether the last Java frame is set */
duke@435 175 public boolean hasLastJavaFrame() {
duke@435 176 return (getLastJavaSP() != null);
duke@435 177 }
duke@435 178
duke@435 179 /** Accessing frames */
duke@435 180 public Frame getLastFrame() {
duke@435 181 // FIXME: would need to implement runtime routine
duke@435 182 // "cacheStatePD(boolean)" for reflective system to be able to
duke@435 183 // flush register windows on SPARC
duke@435 184 return cookLastFrame(getLastFramePD());
duke@435 185 }
duke@435 186
duke@435 187 /** Internal routine implemented by platform-dependent subclasses */
duke@435 188 protected Frame getLastFramePD(){
duke@435 189 return access.getLastFramePD(this, addr);
duke@435 190 }
duke@435 191
duke@435 192 /** Accessing frames. Returns the last Java VFrame or null if none
duke@435 193 was present. (NOTE that this is mostly unusable in a debugging
duke@435 194 system; see getLastJavaVFrameDbg, below, which provides very
duke@435 195 different functionality.) */
duke@435 196 public JavaVFrame getLastJavaVFrame(RegisterMap regMap) {
duke@435 197 if (Assert.ASSERTS_ENABLED) {
duke@435 198 Assert.that(regMap != null, "a map must be given");
duke@435 199 }
duke@435 200 Frame f = getLastFrame();
duke@435 201 if (f == null) {
duke@435 202 return null;
duke@435 203 }
duke@435 204 for (VFrame vf = VFrame.newVFrame(f, regMap, this); vf != null; vf = vf.sender()) {
duke@435 205 if (vf.isJavaFrame()) {
duke@435 206 return (JavaVFrame) vf;
duke@435 207 }
duke@435 208 }
duke@435 209 return null;
duke@435 210 }
duke@435 211
duke@435 212 /** This should only be used by a debugger. Uses the current frame
duke@435 213 guess to attempt to get the topmost JavaVFrame.
duke@435 214 (getLastJavaVFrame, as a port of the VM's routine, assumes the
duke@435 215 VM is at a safepoint.) */
duke@435 216 public JavaVFrame getLastJavaVFrameDbg() {
duke@435 217 RegisterMap regMap = newRegisterMap(true);
duke@435 218 sun.jvm.hotspot.runtime.Frame f = getCurrentFrameGuess();
duke@435 219 if (f == null) return null;
duke@435 220 boolean imprecise = true;
duke@435 221 if (f.isInterpretedFrame() && !f.isInterpretedFrameValid()) {
swamyv@653 222 if (DEBUG) {
swamyv@653 223 System.out.println("Correcting for invalid interpreter frame");
swamyv@653 224 }
swamyv@653 225 f = f.sender(regMap);
swamyv@653 226 imprecise = false;
duke@435 227 }
duke@435 228 VFrame vf = VFrame.newVFrame(f, regMap, this, true, imprecise);
duke@435 229 if (vf == null) {
duke@435 230 if (DEBUG) {
duke@435 231 System.out.println(" (Unable to create vframe for topmost frame guess)");
duke@435 232 }
duke@435 233 return null;
duke@435 234 }
swamyv@653 235 return vf.isJavaFrame() ? (JavaVFrame)vf : vf.javaSender();
duke@435 236 }
duke@435 237
duke@435 238 /** In this system, a JavaThread is the top-level factory for a
duke@435 239 RegisterMap, since the JavaThread implementation is already
duke@435 240 platform-specific and RegisterMap is also necessarily
duke@435 241 platform-specific. The updateMap argument indicates whether the
duke@435 242 register map needs to be updated, for example during stack
duke@435 243 traversal -- see frame.hpp. */
duke@435 244 public RegisterMap newRegisterMap(boolean updateMap){
duke@435 245 return access.newRegisterMap(this, updateMap);
duke@435 246 }
duke@435 247
duke@435 248 /** This is only designed to be used by the debugging system.
duke@435 249 Returns a "best guess" of the topmost frame on the stack. This
duke@435 250 guess should be as "raw" as possible. For example, if the
duke@435 251 topmost frame is an interpreter frame (the return PC is in the
duke@435 252 interpreter) but is not a valid frame (i.e., the BCI has not yet
duke@435 253 been set up) this should still return the topmost frame and not
duke@435 254 the sender. Validity checks are done at higher levels. */
duke@435 255 public Frame getCurrentFrameGuess(){
duke@435 256 return access.getCurrentFrameGuess(this, addr);
duke@435 257 }
duke@435 258
duke@435 259 /** Also only intended for use by the debugging system. Provides the
duke@435 260 same effect of OSThread::print(); that is, prints a value which
duke@435 261 allows the user to intuitively understand which native OS thread
duke@435 262 maps to this Java thread. Does not print a newline or leading or
duke@435 263 trailing spaces. */
duke@435 264 public void printThreadIDOn(PrintStream tty) {
duke@435 265 access.printThreadIDOn(addr,tty);
duke@435 266 }
duke@435 267
duke@435 268 public void printThreadID() {
duke@435 269 printThreadIDOn(System.out);
duke@435 270 }
duke@435 271
duke@435 272 public ThreadProxy getThreadProxy() {
duke@435 273 return access.getThreadProxy(addr);
duke@435 274 }
duke@435 275
duke@435 276 //
duke@435 277 // Safepoint support
duke@435 278 //
duke@435 279
duke@435 280 public JavaThreadState getThreadState() {
duke@435 281 int val = (int) threadStateField.getValue(addr);
duke@435 282 if (val == UNINITIALIZED) {
duke@435 283 return JavaThreadState.UNINITIALIZED;
duke@435 284 } else if (val == NEW) {
duke@435 285 return JavaThreadState.NEW;
duke@435 286 } else if (val == NEW_TRANS) {
duke@435 287 return JavaThreadState.NEW_TRANS;
duke@435 288 } else if (val == IN_NATIVE) {
duke@435 289 return JavaThreadState.IN_NATIVE;
duke@435 290 } else if (val == IN_NATIVE_TRANS) {
duke@435 291 return JavaThreadState.IN_NATIVE_TRANS;
duke@435 292 } else if (val == IN_VM) {
duke@435 293 return JavaThreadState.IN_VM;
duke@435 294 } else if (val == IN_VM_TRANS) {
duke@435 295 return JavaThreadState.IN_VM_TRANS;
duke@435 296 } else if (val == IN_JAVA) {
duke@435 297 return JavaThreadState.IN_JAVA;
duke@435 298 } else if (val == IN_JAVA_TRANS) {
duke@435 299 return JavaThreadState.IN_JAVA_TRANS;
duke@435 300 } else if (val == BLOCKED) {
duke@435 301 return JavaThreadState.BLOCKED;
duke@435 302 } else if (val == BLOCKED_TRANS) {
duke@435 303 return JavaThreadState.BLOCKED_TRANS;
duke@435 304 } else {
duke@435 305 throw new RuntimeException("Illegal thread state " + val);
duke@435 306 }
duke@435 307 }
duke@435 308 // FIXME: not yet implementable
duke@435 309 // public void setThreadState(JavaThreadState s);
duke@435 310
duke@435 311 //
duke@435 312 // Miscellaneous operations
duke@435 313 //
duke@435 314
duke@435 315 public OSThread getOSThread() {
duke@435 316 return (OSThread) VMObjectFactory.newObject(OSThread.class, osThreadField.getValue(addr));
duke@435 317 }
duke@435 318
xlu@1137 319 public Address getStackBase() {
xlu@1209 320 return stackBaseField.getValue(addr);
xlu@1137 321 }
xlu@1137 322
minqi@4750 323 public long getStackBaseValue() {
minqi@4750 324 return VM.getVM().getAddressValue(getStackBase());
minqi@4750 325 }
minqi@4750 326
xlu@1137 327 public long getStackSize() {
xlu@1209 328 return stackSizeField.getValue(addr);
xlu@1137 329 }
xlu@1137 330
duke@435 331 /** Gets the Java-side thread object for this JavaThread */
duke@435 332 public Oop getThreadObj() {
poonam@1888 333 Oop obj = null;
poonam@1888 334 try {
poonam@1888 335 obj = VM.getVM().getObjectHeap().newOop(threadObjField.getValue(addr));
poonam@1888 336 } catch (Exception e) {
poonam@1888 337 e.printStackTrace();
poonam@1888 338 }
poonam@1888 339 return obj;
duke@435 340 }
duke@435 341
duke@435 342 /** Get the Java-side name of this thread */
duke@435 343 public String getThreadName() {
duke@435 344 Oop threadObj = getThreadObj();
duke@435 345 if (threadObj == null) {
duke@435 346 return "<null>";
duke@435 347 }
duke@435 348 return OopUtilities.threadOopGetName(threadObj);
duke@435 349 }
duke@435 350
duke@435 351 //
duke@435 352 // Oop traversal
duke@435 353 //
duke@435 354
duke@435 355 public void oopsDo(AddressVisitor oopVisitor) {
duke@435 356 super.oopsDo(oopVisitor);
duke@435 357
duke@435 358 // FIXME: add in the rest of the routine from the VM
duke@435 359
duke@435 360 // Traverse the execution stack
duke@435 361 for(StackFrameStream fst = new StackFrameStream(this); !fst.isDone(); fst.next()) {
duke@435 362 fst.getCurrent().oopsDo(oopVisitor, fst.getRegisterMap());
duke@435 363 }
duke@435 364 }
duke@435 365
duke@435 366 public boolean isInStack(Address a) {
duke@435 367 if (Assert.ASSERTS_ENABLED) {
duke@435 368 Assert.that(VM.getVM().isDebugging(), "Not yet implemented for non-debugging system");
duke@435 369 }
duke@435 370 Address sp = lastSPDbg();
xlu@1137 371 Address stackBase = getStackBase();
duke@435 372 // Be robust
xlu@1137 373 if (sp == null) return false;
dholmes@9903 374 return stackBase.greaterThan(a) && sp.lessThanOrEqual(a);
xlu@1137 375 }
xlu@1137 376
xlu@1137 377 public boolean isLockOwned(Address a) {
xlu@1137 378 Address stackBase = getStackBase();
xlu@1137 379 Address stackLimit = stackBase.addOffsetTo(-getStackSize());
xlu@1137 380
dholmes@9903 381 return stackBase.greaterThan(a) && stackLimit.lessThanOrEqual(a);
duke@435 382
duke@435 383 // FIXME: should traverse MonitorArray/MonitorChunks as in VM
duke@435 384 }
duke@435 385
duke@435 386 public Oop getCurrentParkBlocker() {
duke@435 387 Oop threadObj = getThreadObj();
duke@435 388 if (threadObj != null) {
duke@435 389 return OopUtilities.threadOopGetParkBlocker(threadObj);
duke@435 390 }
duke@435 391 return null;
duke@435 392 }
duke@435 393
duke@435 394 public void printInfoOn(PrintStream tty) {
duke@435 395
duke@435 396 tty.println("State: " + getThreadState().toString());
duke@435 397 // Attempt to figure out the addresses covered by Java frames.
duke@435 398 // NOTE: we should make this a method and let the Stackwalk panel use the result too.
duke@435 399 //
duke@435 400 sun.jvm.hotspot.runtime.Frame tmpFrame = getCurrentFrameGuess();
duke@435 401 if (tmpFrame != null ) {
duke@435 402 Address sp = tmpFrame.getSP();
duke@435 403 Address maxSP = sp;
duke@435 404 Address minSP = sp;
duke@435 405 RegisterMap tmpMap = newRegisterMap(false);
duke@435 406 while ((tmpFrame != null) && (!tmpFrame.isFirstFrame())) {
duke@435 407 tmpFrame = tmpFrame.sender(tmpMap);
duke@435 408 if (tmpFrame != null) {
duke@435 409 sp = tmpFrame.getSP();
duke@435 410 maxSP = AddressOps.max(maxSP, sp);
duke@435 411 minSP = AddressOps.min(minSP, sp);
duke@435 412 }
duke@435 413 }
duke@435 414 tty.println("Stack in use by Java: " + minSP + " .. " + maxSP);
duke@435 415 } else {
duke@435 416 tty.println("No Java frames present");
duke@435 417 }
poonam@8191 418 tty.println("Base of Stack: " + getStackBase());
duke@435 419 tty.println("Last_Java_SP: " + getLastJavaSP());
duke@435 420 tty.println("Last_Java_FP: " + getLastJavaFP());
duke@435 421 tty.println("Last_Java_PC: " + getLastJavaPC());
duke@435 422 // More stuff like saved_execption_pc, safepoint_state, ...
duke@435 423 access.printInfoOn(addr, tty);
duke@435 424
duke@435 425 }
duke@435 426
duke@435 427 ///////////////////////////////
duke@435 428 // //
duke@435 429 // FIXME: add more accessors //
duke@435 430 // //
duke@435 431 ///////////////////////////////
duke@435 432
duke@435 433 //--------------------------------------------------------------------------------
duke@435 434 // Internals only below this point
duke@435 435 //
duke@435 436
duke@435 437 private Frame cookLastFrame(Frame fr) {
duke@435 438 if (fr == null) {
duke@435 439 return null;
duke@435 440 }
duke@435 441
duke@435 442 Address pc = fr.getPC();
duke@435 443
duke@435 444 if (Assert.ASSERTS_ENABLED) {
duke@435 445 if (pc == null) {
duke@435 446 Assert.that(VM.getVM().isDebugging(), "must have PC");
duke@435 447 }
duke@435 448 }
duke@435 449 return fr;
duke@435 450 }
duke@435 451
duke@435 452 private Address lastSPDbg() {
duke@435 453 return access.getLastSP(addr);
duke@435 454 }
duke@435 455
duke@435 456 }

mercurial