1 /*
  2  * Copyright (c) 2000, 2022, 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 
 25 package sun.jvm.hotspot.runtime;
 26 
 27 import java.io.*;
 28 import java.util.*;
 29 import sun.jvm.hotspot.debugger.*;
 30 import sun.jvm.hotspot.oops.*;
 31 import sun.jvm.hotspot.types.*;
 32 import sun.jvm.hotspot.utilities.*;
 33 import sun.jvm.hotspot.utilities.Observable;
 34 import sun.jvm.hotspot.utilities.Observer;
 35 
 36 /** This is an abstract class because there are certain OS- and
 37     CPU-specific operations (like the setting and getting of the last
 38     Java frame pointer) which need to be factored out. These
 39     operations are implemented by, for example,
 40     SolarisSPARCJavaThread, and the concrete subclasses are
 41     instantiated by the JavaThreadFactory in the Threads class. */
 42 
 43 public class JavaThread extends Thread {
 44   private static final boolean DEBUG = System.getProperty("sun.jvm.hotspot.runtime.JavaThread.DEBUG") != null;
 45 
 46   private static long          threadObjFieldOffset;
 47   private static long          lockStackTopOffset;
 48   private static long          lockStackBaseOffset;
 49   private static AddressField  anchorField;
 50   private static AddressField  lastJavaSPField;
 51   private static AddressField  lastJavaPCField;
 52   private static CIntegerField threadStateField;
 53   private static AddressField  osThreadField;
 54   private static AddressField  stackBaseField;
 55   private static CIntegerField stackSizeField;
 56   private static CIntegerField terminatedField;
 57   private static AddressField activeHandlesField;
 58   private static long oopPtrSize;
 59 
 60   private static JavaThreadPDAccess access;
 61 
 62   // JavaThreadStates read from underlying process
 63   private static int           UNINITIALIZED;
 64   private static int           NEW;
 65   private static int           NEW_TRANS;
 66   private static int           IN_NATIVE;
 67   private static int           IN_NATIVE_TRANS;
 68   private static int           IN_VM;
 69   private static int           IN_VM_TRANS;
 70   private static int           IN_JAVA;
 71   private static int           IN_JAVA_TRANS;
 72   private static int           BLOCKED;
 73   private static int           BLOCKED_TRANS;
 74 
 75   private static int           NOT_TERMINATED;
 76   private static int           EXITING;
 77 
 78   private static final String  ADDRESS_FORMAT = VM.getVM().isLP64() ? "0x%016x" : "0x%08x";
 79 
 80   static {
 81     VM.registerVMInitializedObserver(new Observer() {
 82         public void update(Observable o, Object data) {
 83           initialize(VM.getVM().getTypeDataBase());
 84         }
 85       });
 86   }
 87 
 88   private static synchronized void initialize(TypeDataBase db) {
 89     Type type = db.lookupType("JavaThread");
 90     Type anchorType = db.lookupType("JavaFrameAnchor");
 91     Type typeLockStack = db.lookupType("LockStack");
 92 
 93     threadObjFieldOffset = type.getField("_threadObj").getOffset();
 94 
 95     anchorField       = type.getAddressField("_anchor");
 96     lastJavaSPField   = anchorType.getAddressField("_last_Java_sp");
 97     lastJavaPCField   = anchorType.getAddressField("_last_Java_pc");
 98     threadStateField  = type.getCIntegerField("_thread_state");
 99     osThreadField     = type.getAddressField("_osthread");
100     stackBaseField    = type.getAddressField("_stack_base");
101     stackSizeField    = type.getCIntegerField("_stack_size");
102     terminatedField   = type.getCIntegerField("_terminated");
103     activeHandlesField = type.getAddressField("_active_handles");
104 
105     lockStackTopOffset = type.getField("_lock_stack").getOffset() + typeLockStack.getField("_top").getOffset();
106     lockStackBaseOffset = type.getField("_lock_stack").getOffset() + typeLockStack.getField("_base[0]").getOffset();
107     oopPtrSize = VM.getVM().getAddressSize();
108 
109     UNINITIALIZED     = db.lookupIntConstant("_thread_uninitialized").intValue();
110     NEW               = db.lookupIntConstant("_thread_new").intValue();
111     NEW_TRANS         = db.lookupIntConstant("_thread_new_trans").intValue();
112     IN_NATIVE         = db.lookupIntConstant("_thread_in_native").intValue();
113     IN_NATIVE_TRANS   = db.lookupIntConstant("_thread_in_native_trans").intValue();
114     IN_VM             = db.lookupIntConstant("_thread_in_vm").intValue();
115     IN_VM_TRANS       = db.lookupIntConstant("_thread_in_vm_trans").intValue();
116     IN_JAVA           = db.lookupIntConstant("_thread_in_Java").intValue();
117     IN_JAVA_TRANS     = db.lookupIntConstant("_thread_in_Java_trans").intValue();
118     BLOCKED           = db.lookupIntConstant("_thread_blocked").intValue();
119     BLOCKED_TRANS     = db.lookupIntConstant("_thread_blocked_trans").intValue();
120 
121     NOT_TERMINATED    = db.lookupIntConstant("JavaThread::_not_terminated").intValue();
122     EXITING           = db.lookupIntConstant("JavaThread::_thread_exiting").intValue();
123 
124   }
125 
126   public JavaThread(Address addr) {
127     super(addr);
128   }
129 
130   void setThreadPDAccess(JavaThreadPDAccess access) {
131     this.access = access;
132   }
133 
134   /** NOTE: for convenience, this differs in definition from the underlying VM.
135       Only "pure" JavaThreads return true; CompilerThreads,
136       JVMDIDebuggerThreads return false.
137       FIXME:
138       consider encapsulating platform-specific functionality in an
139       object instead of using inheritance (which is the primary reason
140       we can't traverse CompilerThreads, etc; didn't want to have, for
141       example, "SolarisSPARCCompilerThread".) */
142   public boolean isJavaThread() { return true; }
143 
144   public boolean isExiting () {
145       return (getTerminated() == EXITING) || isTerminated();
146   }
147 
148   public boolean isTerminated() {
149       return (getTerminated() != NOT_TERMINATED) && (getTerminated() != EXITING);
150   }
151 
152   public static AddressField getAnchorField() { return anchorField; }
153 
154   /** Get the last Java stack pointer */
155   public Address getLastJavaSP() {
156     Address sp = lastJavaSPField.getValue(addr.addOffsetTo(anchorField.getOffset()));
157     return sp;
158   }
159 
160   public Address getLastJavaPC() {
161     Address pc = lastJavaPCField.getValue(addr.addOffsetTo(anchorField.getOffset()));
162     return pc;
163   }
164 
165   /** Abstract accessor to last Java frame pointer, implemented by
166       OS/CPU-specific JavaThread implementation. May return null if
167       there is no frame pointer or if it is not necessary on this
168       platform. */
169   public Address getLastJavaFP(){
170         return access.getLastJavaFP(addr);
171   }
172 
173   /** Abstract accessor to last Java pc, implemented by
174       OS/CPU-specific JavaThread implementation. May return null if
175       there is no frame pointer or if it is not necessary on this
176       platform. */
177 
178   /*
179   public Address getLastJavaPC(){
180         return access.getLastJavaPC(addr);
181   }
182   */
183 
184   // FIXME: not yet implementable
185   //  public abstract void    setLastJavaFP(Address fp);
186 
187   /** A stack pointer older than any java frame stack pointer. Only
188       needed on some platforms; for example, see
189       thread_solaris_sparc.hpp. */
190   public Address getBaseOfStackPointer(){
191         return access.getBaseOfStackPointer(addr);
192   }
193   // FIXME: not yet implementable
194   //  public abstract void    setBaseOfStackPointer(Address fp);
195 
196   /** Tells whether the last Java frame is set */
197   public boolean hasLastJavaFrame() {
198     return (getLastJavaSP() != null);
199   }
200 
201   /** Accessing frames */
202   public Frame getLastFrame() {
203     // FIXME: would need to implement runtime routine
204     // "cacheStatePD(boolean)" for reflective system to be able to
205     // flush register windows on SPARC
206     return cookLastFrame(getLastFramePD());
207   }
208 
209   /** Internal routine implemented by platform-dependent subclasses */
210   protected Frame getLastFramePD(){
211         return access.getLastFramePD(this, addr);
212   }
213 
214   /** Accessing frames. Returns the last Java VFrame or null if none
215       was present. (NOTE that this is mostly unusable in a debugging
216       system; see getLastJavaVFrameDbg, below, which provides very
217       different functionality.) */
218   public JavaVFrame getLastJavaVFrame(RegisterMap regMap) {
219     if (Assert.ASSERTS_ENABLED) {
220       Assert.that(regMap != null, "a map must be given");
221     }
222     Frame f = getLastFrame();
223     if (f == null) {
224       return null;
225     }
226     for (VFrame vf = VFrame.newVFrame(f, regMap, this); vf != null; vf = vf.sender()) {
227       if (vf.isJavaFrame()) {
228         return (JavaVFrame) vf;
229       }
230     }
231     return null;
232   }
233 
234   /** This should only be used by a debugger. Uses the current frame
235       guess to attempt to get the topmost JavaVFrame.
236       (getLastJavaVFrame, as a port of the VM's routine, assumes the
237       VM is at a safepoint.) */
238   public JavaVFrame getLastJavaVFrameDbg() {
239     RegisterMap regMap = newRegisterMap(true);
240     sun.jvm.hotspot.runtime.Frame f = getCurrentFrameGuess();
241     if (f == null) return null;
242     boolean imprecise = true;
243     if (f.isInterpretedFrame() && !f.isInterpretedFrameValid()) {
244        if (DEBUG) {
245          System.out.println("Correcting for invalid interpreter frame");
246        }
247        f = f.sender(regMap);
248        imprecise = false;
249     }
250     VFrame vf = VFrame.newVFrame(f, regMap, this, true, imprecise);
251     if (vf == null) {
252       if (DEBUG) {
253         System.out.println(" (Unable to create vframe for topmost frame guess)");
254       }
255       return null;
256     }
257     return vf.isJavaFrame() ? (JavaVFrame)vf : vf.javaSender();
258   }
259 
260   /** In this system, a JavaThread is the top-level factory for a
261       RegisterMap, since the JavaThread implementation is already
262       platform-specific and RegisterMap is also necessarily
263       platform-specific. The updateMap argument indicates whether the
264       register map needs to be updated, for example during stack
265       traversal -- see frame.hpp. */
266   public RegisterMap newRegisterMap(boolean updateMap){
267         return access.newRegisterMap(this, updateMap);
268   }
269 
270   /** This is only designed to be used by the debugging system.
271       Returns a "best guess" of the topmost frame on the stack. This
272       guess should be as "raw" as possible. For example, if the
273       topmost frame is an interpreter frame (the return PC is in the
274       interpreter) but is not a valid frame (i.e., the BCI has not yet
275       been set up) this should still return the topmost frame and not
276       the sender. Validity checks are done at higher levels. */
277   public  Frame getCurrentFrameGuess(){
278         return access.getCurrentFrameGuess(this, addr);
279   }
280 
281   /** Also only intended for use by the debugging system. Provides the
282       same effect of OSThread::print(); that is, prints a value which
283       allows the user to intuitively understand which native OS thread
284       maps to this Java thread. Does not print a newline or leading or
285       trailing spaces. */
286   public  void printThreadIDOn(PrintStream tty) {
287         access.printThreadIDOn(addr,tty);
288   }
289 
290   public void printThreadID() {
291     printThreadIDOn(System.out);
292   }
293 
294   public ThreadProxy getThreadProxy() {
295     return access.getThreadProxy(addr);
296   }
297 
298   //
299   // Safepoint support
300   //
301 
302   public JavaThreadState getThreadState() {
303     int val = (int) threadStateField.getValue(addr);
304     if (val == UNINITIALIZED) {
305       return JavaThreadState.UNINITIALIZED;
306     } else if (val == NEW) {
307       return JavaThreadState.NEW;
308     } else if (val == NEW_TRANS) {
309       return JavaThreadState.NEW_TRANS;
310     } else if (val == IN_NATIVE) {
311       return JavaThreadState.IN_NATIVE;
312     } else if (val == IN_NATIVE_TRANS) {
313       return JavaThreadState.IN_NATIVE_TRANS;
314     } else if (val == IN_VM) {
315       return JavaThreadState.IN_VM;
316     } else if (val == IN_VM_TRANS) {
317       return JavaThreadState.IN_VM_TRANS;
318     } else if (val == IN_JAVA) {
319       return JavaThreadState.IN_JAVA;
320     } else if (val == IN_JAVA_TRANS) {
321       return JavaThreadState.IN_JAVA_TRANS;
322     } else if (val == BLOCKED) {
323       return JavaThreadState.BLOCKED;
324     } else if (val == BLOCKED_TRANS) {
325       return JavaThreadState.BLOCKED_TRANS;
326     } else {
327       throw new RuntimeException("Illegal thread state " + val);
328     }
329   }
330   // FIXME: not yet implementable
331   // public void setThreadState(JavaThreadState s);
332 
333   //
334   // Miscellaneous operations
335   //
336 
337   public OSThread getOSThread() {
338     return VMObjectFactory.newObject(OSThread.class, osThreadField.getValue(addr));
339   }
340 
341   public Address getStackBase() {
342     return stackBaseField.getValue(addr);
343   }
344 
345   public long getStackBaseValue() {
346     return VM.getVM().getAddressValue(getStackBase());
347   }
348 
349   public long getStackSize() {
350     return stackSizeField.getValue(addr);
351   }
352 
353   public int getTerminated() {
354       return (int) terminatedField.getValue(addr);
355   }
356 
357   /** Gets the Java-side thread object for this JavaThread */
358   public Oop getThreadObj() {
359     Oop obj = null;
360     try {
361       Address addr = getAddress().addOffsetTo(threadObjFieldOffset);
362       VMOopHandle vmOopHandle = VMObjectFactory.newObject(VMOopHandle.class, addr);
363       obj = vmOopHandle.resolve();
364     } catch (Exception e) {
365       System.out.println("WARNING: could not get Thread object: " + e);
366     }
367     return obj;
368   }
369 
370   /** Get the Java-side name of this thread */
371   public String getThreadName() {
372     Oop threadObj = getThreadObj();
373     if (threadObj == null) {
374         return "<null>";
375     }
376     return OopUtilities.threadOopGetName(threadObj);
377   }
378 
379   //
380   // Oop traversal
381   //
382 
383   public void oopsDo(AddressVisitor oopVisitor) {
384     super.oopsDo(oopVisitor);
385 
386     // FIXME: add in the rest of the routine from the VM
387 
388     // Traverse the execution stack
389     for(StackFrameStream fst = new StackFrameStream(this); !fst.isDone(); fst.next()) {
390       fst.getCurrent().oopsDo(oopVisitor, fst.getRegisterMap());
391     }
392   }
393 
394   public boolean isInStack(Address a) {
395     if (Assert.ASSERTS_ENABLED) {
396       Assert.that(VM.getVM().isDebugging(), "Not yet implemented for non-debugging system");
397     }
398     Address sp      = lastSPDbg();
399     Address stackBase = getStackBase();
400     // Be robust
401     if (sp == null) return false;
402     return stackBase.greaterThan(a) && sp.lessThanOrEqual(a);
403   }
404 
405   public boolean isLockOwned(OopHandle obj) {
406     long current = lockStackBaseOffset;
407     long end = addr.getJIntAt(lockStackTopOffset);
408     if (Assert.ASSERTS_ENABLED) {
409       Assert.that(current <= end, "current stack offset must be above base offset");
410     }
411 
412     while (current < end) {
413       Address oop = addr.getAddressAt(current);
414       if (oop.equals(obj)) {
415         return true;
416       }
417       current += oopPtrSize;
418     }
419     return false;
420   }
421 
422   public boolean isLockOwned(Address a) {
423     Address stackBase = getStackBase();
424     Address stackLimit = stackBase.addOffsetTo(-getStackSize());
425 
426     return stackBase.greaterThan(a) && stackLimit.lessThanOrEqual(a);
427 
428     // FIXME: should traverse MonitorArray/MonitorChunks as in VM
429   }
430 
431   public Oop getCurrentParkBlocker() {
432     Oop threadObj = getThreadObj();
433     if (threadObj != null) {
434       try {
435         return OopUtilities.threadOopGetParkBlocker(threadObj);
436       } catch (Exception e) {
437         System.out.println("Could not get current park blocker: " + e);
438       }
439     }
440     return null;
441   }
442 
443   public JNIHandleBlock activeHandles() {
444     Address a = activeHandlesField.getAddress(addr);
445     if (a == null) {
446       return null;
447     }
448     return new JNIHandleBlock(a);
449   }
450 
451   public void printInfoOn(PrintStream tty) {
452 
453     tty.println("State: " + getThreadState().toString());
454     // Attempt to figure out the addresses covered by Java frames.
455     // NOTE: we should make this a method and let the Stackwalk panel use the result too.
456     //
457     sun.jvm.hotspot.runtime.Frame tmpFrame = getCurrentFrameGuess();
458     if (tmpFrame != null ) {
459       Address sp = tmpFrame.getSP();
460       Address maxSP = sp;
461       Address minSP = sp;
462       RegisterMap tmpMap = newRegisterMap(false);
463       while ((tmpFrame != null) && (!tmpFrame.isFirstFrame())) {
464           tmpFrame = tmpFrame.sender(tmpMap);
465           if (tmpFrame != null) {
466             sp = tmpFrame.getSP();
467             maxSP = AddressOps.max(maxSP, sp);
468             minSP = AddressOps.min(minSP, sp);
469           }
470       }
471       tty.println("Stack in use by Java: " + minSP + " .. " + maxSP);
472     } else {
473       tty.println("No Java frames present");
474     }
475     tty.println("Base of Stack: " + getStackBase());
476     tty.println("Last_Java_SP: " + getLastJavaSP());
477     tty.println("Last_Java_FP: " + getLastJavaFP());
478     tty.println("Last_Java_PC: " + getLastJavaPC());
479     // More stuff like saved_execption_pc, safepoint_state, ...
480     access.printInfoOn(addr, tty);
481 
482   }
483 
484   ///////////////////////////////
485   //                           //
486   // FIXME: add more accessors //
487   //                           //
488   ///////////////////////////////
489 
490   //--------------------------------------------------------------------------------
491   // Internals only below this point
492   //
493 
494   private Frame cookLastFrame(Frame fr) {
495     if (fr == null) {
496       return null;
497     }
498 
499     Address pc        = fr.getPC();
500 
501     if (Assert.ASSERTS_ENABLED) {
502       if (pc == null) {
503         Assert.that(VM.getVM().isDebugging(), "must have PC");
504       }
505     }
506     return fr;
507   }
508 
509   public Address lastSPDbg() {
510     return access.getLastSP(addr);
511   }
512 
513   // Print the contents of all registers in the thread's context
514   public void printThreadContextOn(PrintStream out, boolean verbose){
515     ThreadContext tc = getThreadProxy().getContext();
516     for (int r = 0; r < tc.getNumRegisters(); r++) {
517       Address regAddr = tc.getRegisterAsAddress(r);
518       System.out.format("%s: %s", tc.getRegisterName(r), regAddr);
519       if (regAddr == null) {
520         System.out.println();
521       } else {
522         PointerLocation l = PointerFinder.find(regAddr);
523         if (l.isUnknown()) {
524           System.out.println();
525         } else {
526           System.out.print(": ");
527           l.printOn(System.out, false, verbose);
528         }
529       }
530     }
531   }
532 
533   public void printThreadInfoOn(PrintStream out){
534       String threadName = "<unknown>";
535       boolean daemon = false;
536       int priority = java.lang.Thread.MIN_PRIORITY - 1;
537       String statusName = "<unknown>";
538 
539       Oop threadOop = this.getThreadObj();
540       if (threadOop == null) {
541           System.out.println("Could not get the java Thread object. Thread info will be limited.");
542       } else {
543           // Some of these accesses can throw an Exception if we are in the
544           // middle of a GC, so be cautious.
545           try {
546               threadName = this.getThreadName();
547           } catch (Exception e) {}
548           try {
549               // These all rely on the FieldHolder object, so if one fails, they all fail.
550               daemon = OopUtilities.threadOopGetDaemon(threadOop);
551               priority = OopUtilities.threadOopGetPriority(threadOop);
552               statusName = OopUtilities.threadOopGetThreadStatusName(threadOop);
553           } catch (Exception e) {}
554           out.print("\"");
555           out.print(threadName);
556           out.print("\" #");
557           out.print(OopUtilities.threadOopGetTID(threadOop));
558           if (daemon) {
559               out.print(" daemon");
560           }
561           out.print(" prio=");
562           if (priority == java.lang.Thread.MIN_PRIORITY - 1) {
563               out.print("<unknown>");
564           } else {
565               out.print(priority);
566           }
567       }
568       out.print(" tid=");
569       out.print(this.getAddress());
570       out.print(" nid=");
571       out.print(String.format("%d ", this.getOSThread().threadId()));
572       out.print(getOSThread().getThreadState().getPrintVal());
573       out.print(" [");
574       if (this.getLastJavaSP() == null) {
575           out.print(String.format(ADDRESS_FORMAT, 0L));
576       } else {
577           out.print(this.getLastJavaSP().andWithMask(~0xFFF));
578       }
579       out.println("]");
580       if (threadOop != null) {
581           out.print("   java.lang.Thread.State: ");
582           out.println(statusName);
583       }
584       out.print("   JavaThread state: _thread_");
585       out.println(this.getThreadState().toString().toLowerCase());
586   }
587 }