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