comparison agent/src/share/classes/sun/jvm/hotspot/runtime/JavaThread.java @ 0:a61af66fc99e jdk7-b24

Initial load
author duke
date Sat, 01 Dec 2007 00:00:00 +0000
parents
children a5838065ab24
comparison
equal deleted inserted replaced
-1:000000000000 0:a61af66fc99e
1 /*
2 * Copyright 2000-2005 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
20 * CA 95054 USA or visit www.sun.com if you need additional information or
21 * have any 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
52 private static JavaThreadPDAccess access;
53
54 // JavaThreadStates read from underlying process
55 private static int UNINITIALIZED;
56 private static int NEW;
57 private static int NEW_TRANS;
58 private static int IN_NATIVE;
59 private static int IN_NATIVE_TRANS;
60 private static int IN_VM;
61 private static int IN_VM_TRANS;
62 private static int IN_JAVA;
63 private static int IN_JAVA_TRANS;
64 private static int BLOCKED;
65 private static int BLOCKED_TRANS;
66
67 static {
68 VM.registerVMInitializedObserver(new Observer() {
69 public void update(Observable o, Object data) {
70 initialize(VM.getVM().getTypeDataBase());
71 }
72 });
73 }
74
75 private static synchronized void initialize(TypeDataBase db) {
76 Type type = db.lookupType("JavaThread");
77 Type anchorType = db.lookupType("JavaFrameAnchor");
78
79 nextField = type.getAddressField("_next");
80 threadObjField = type.getOopField("_threadObj");
81 anchorField = type.getAddressField("_anchor");
82 lastJavaSPField = anchorType.getAddressField("_last_Java_sp");
83 lastJavaPCField = anchorType.getAddressField("_last_Java_pc");
84 threadStateField = type.getCIntegerField("_thread_state");
85 osThreadField = type.getAddressField("_osthread");
86
87 UNINITIALIZED = db.lookupIntConstant("_thread_uninitialized").intValue();
88 NEW = db.lookupIntConstant("_thread_new").intValue();
89 NEW_TRANS = db.lookupIntConstant("_thread_new_trans").intValue();
90 IN_NATIVE = db.lookupIntConstant("_thread_in_native").intValue();
91 IN_NATIVE_TRANS = db.lookupIntConstant("_thread_in_native_trans").intValue();
92 IN_VM = db.lookupIntConstant("_thread_in_vm").intValue();
93 IN_VM_TRANS = db.lookupIntConstant("_thread_in_vm_trans").intValue();
94 IN_JAVA = db.lookupIntConstant("_thread_in_Java").intValue();
95 IN_JAVA_TRANS = db.lookupIntConstant("_thread_in_Java_trans").intValue();
96 BLOCKED = db.lookupIntConstant("_thread_blocked").intValue();
97 BLOCKED_TRANS = db.lookupIntConstant("_thread_blocked_trans").intValue();
98 }
99
100 public JavaThread(Address addr) {
101 super(addr);
102 }
103
104 void setThreadPDAccess(JavaThreadPDAccess access) {
105 this.access = access;
106 }
107
108 public JavaThread next() {
109 Address threadAddr = nextField.getValue(addr);
110 if (threadAddr == null) {
111 return null;
112 }
113
114 return VM.getVM().getThreads().createJavaThreadWrapper(threadAddr);
115 }
116
117 /** NOTE: for convenience, this differs in definition from the
118 underlying VM. Only "pure" JavaThreads return true;
119 CompilerThreads and JVMDIDebuggerThreads return false. FIXME:
120 consider encapsulating platform-specific functionality in an
121 object instead of using inheritance (which is the primary reason
122 we can't traverse CompilerThreads, etc; didn't want to have, for
123 example, "SolarisSPARCCompilerThread".) */
124 public boolean isJavaThread() { return true; }
125
126 public static AddressField getAnchorField() { return anchorField; }
127
128 /** Get the last Java stack pointer */
129 public Address getLastJavaSP() {
130 Address sp = lastJavaSPField.getValue(addr.addOffsetTo(anchorField.getOffset()));
131 return sp;
132 }
133
134 public Address getLastJavaPC() {
135 Address pc = lastJavaPCField.getValue(addr.addOffsetTo(anchorField.getOffset()));
136 return pc;
137 }
138
139 /** Abstract accessor to last Java frame pointer, implemented by
140 OS/CPU-specific JavaThread implementation. May return null if
141 there is no frame pointer or if it is not necessary on this
142 platform. */
143 public Address getLastJavaFP(){
144 return access.getLastJavaFP(addr);
145 }
146
147 /** Abstract accessor to last Java pc, implemented by
148 OS/CPU-specific JavaThread implementation. May return null if
149 there is no frame pointer or if it is not necessary on this
150 platform. */
151
152 /*
153 public Address getLastJavaPC(){
154 return access.getLastJavaPC(addr);
155 }
156 */
157
158 // FIXME: not yet implementable
159 // public abstract void setLastJavaFP(Address fp);
160
161 /** A stack pointer older than any java frame stack pointer. Only
162 needed on some platforms; for example, see
163 thread_solaris_sparc.hpp. */
164 public Address getBaseOfStackPointer(){
165 return access.getBaseOfStackPointer(addr);
166 }
167 // FIXME: not yet implementable
168 // public abstract void setBaseOfStackPointer(Address fp);
169
170 /** Tells whether the last Java frame is set */
171 public boolean hasLastJavaFrame() {
172 return (getLastJavaSP() != null);
173 }
174
175 /** Accessing frames */
176 public Frame getLastFrame() {
177 // FIXME: would need to implement runtime routine
178 // "cacheStatePD(boolean)" for reflective system to be able to
179 // flush register windows on SPARC
180 return cookLastFrame(getLastFramePD());
181 }
182
183 /** Internal routine implemented by platform-dependent subclasses */
184 protected Frame getLastFramePD(){
185 return access.getLastFramePD(this, addr);
186 }
187
188 /** Accessing frames. Returns the last Java VFrame or null if none
189 was present. (NOTE that this is mostly unusable in a debugging
190 system; see getLastJavaVFrameDbg, below, which provides very
191 different functionality.) */
192 public JavaVFrame getLastJavaVFrame(RegisterMap regMap) {
193 if (Assert.ASSERTS_ENABLED) {
194 Assert.that(regMap != null, "a map must be given");
195 }
196 Frame f = getLastFrame();
197 if (f == null) {
198 return null;
199 }
200 for (VFrame vf = VFrame.newVFrame(f, regMap, this); vf != null; vf = vf.sender()) {
201 if (vf.isJavaFrame()) {
202 return (JavaVFrame) vf;
203 }
204 }
205 return null;
206 }
207
208 /** This should only be used by a debugger. Uses the current frame
209 guess to attempt to get the topmost JavaVFrame.
210 (getLastJavaVFrame, as a port of the VM's routine, assumes the
211 VM is at a safepoint.) */
212 public JavaVFrame getLastJavaVFrameDbg() {
213 RegisterMap regMap = newRegisterMap(true);
214 sun.jvm.hotspot.runtime.Frame f = getCurrentFrameGuess();
215 if (f == null) return null;
216 boolean imprecise = true;
217 if (f.isInterpretedFrame() && !f.isInterpretedFrameValid()) {
218 if (DEBUG) {
219 System.out.println("Correcting for invalid interpreter frame");
220 }
221 f = f.sender(regMap);
222 imprecise = false;
223 }
224 VFrame vf = VFrame.newVFrame(f, regMap, this, true, imprecise);
225 if (vf == null) {
226 if (DEBUG) {
227 System.out.println(" (Unable to create vframe for topmost frame guess)");
228 }
229 return null;
230 }
231 if (vf.isJavaFrame()) {
232 return (JavaVFrame) vf;
233 }
234 return (JavaVFrame) vf.javaSender();
235 }
236
237 /** In this system, a JavaThread is the top-level factory for a
238 RegisterMap, since the JavaThread implementation is already
239 platform-specific and RegisterMap is also necessarily
240 platform-specific. The updateMap argument indicates whether the
241 register map needs to be updated, for example during stack
242 traversal -- see frame.hpp. */
243 public RegisterMap newRegisterMap(boolean updateMap){
244 return access.newRegisterMap(this, updateMap);
245 }
246
247 /** This is only designed to be used by the debugging system.
248 Returns a "best guess" of the topmost frame on the stack. This
249 guess should be as "raw" as possible. For example, if the
250 topmost frame is an interpreter frame (the return PC is in the
251 interpreter) but is not a valid frame (i.e., the BCI has not yet
252 been set up) this should still return the topmost frame and not
253 the sender. Validity checks are done at higher levels. */
254 public Frame getCurrentFrameGuess(){
255 return access.getCurrentFrameGuess(this, addr);
256 }
257
258 /** Also only intended for use by the debugging system. Provides the
259 same effect of OSThread::print(); that is, prints a value which
260 allows the user to intuitively understand which native OS thread
261 maps to this Java thread. Does not print a newline or leading or
262 trailing spaces. */
263 public void printThreadIDOn(PrintStream tty) {
264 access.printThreadIDOn(addr,tty);
265 }
266
267 public void printThreadID() {
268 printThreadIDOn(System.out);
269 }
270
271 public ThreadProxy getThreadProxy() {
272 return access.getThreadProxy(addr);
273 }
274
275 //
276 // Safepoint support
277 //
278
279 public JavaThreadState getThreadState() {
280 int val = (int) threadStateField.getValue(addr);
281 if (val == UNINITIALIZED) {
282 return JavaThreadState.UNINITIALIZED;
283 } else if (val == NEW) {
284 return JavaThreadState.NEW;
285 } else if (val == NEW_TRANS) {
286 return JavaThreadState.NEW_TRANS;
287 } else if (val == IN_NATIVE) {
288 return JavaThreadState.IN_NATIVE;
289 } else if (val == IN_NATIVE_TRANS) {
290 return JavaThreadState.IN_NATIVE_TRANS;
291 } else if (val == IN_VM) {
292 return JavaThreadState.IN_VM;
293 } else if (val == IN_VM_TRANS) {
294 return JavaThreadState.IN_VM_TRANS;
295 } else if (val == IN_JAVA) {
296 return JavaThreadState.IN_JAVA;
297 } else if (val == IN_JAVA_TRANS) {
298 return JavaThreadState.IN_JAVA_TRANS;
299 } else if (val == BLOCKED) {
300 return JavaThreadState.BLOCKED;
301 } else if (val == BLOCKED_TRANS) {
302 return JavaThreadState.BLOCKED_TRANS;
303 } else {
304 throw new RuntimeException("Illegal thread state " + val);
305 }
306 }
307 // FIXME: not yet implementable
308 // public void setThreadState(JavaThreadState s);
309
310 //
311 // Miscellaneous operations
312 //
313
314 public OSThread getOSThread() {
315 return (OSThread) VMObjectFactory.newObject(OSThread.class, osThreadField.getValue(addr));
316 }
317
318 /** Gets the Java-side thread object for this JavaThread */
319 public Oop getThreadObj() {
320 return VM.getVM().getObjectHeap().newOop(threadObjField.getValue(addr));
321 }
322
323 /** Get the Java-side name of this thread */
324 public String getThreadName() {
325 Oop threadObj = getThreadObj();
326 if (threadObj == null) {
327 return "<null>";
328 }
329 return OopUtilities.threadOopGetName(threadObj);
330 }
331
332 //
333 // Oop traversal
334 //
335
336 public void oopsDo(AddressVisitor oopVisitor) {
337 super.oopsDo(oopVisitor);
338
339 // FIXME: add in the rest of the routine from the VM
340
341 // Traverse the execution stack
342 for(StackFrameStream fst = new StackFrameStream(this); !fst.isDone(); fst.next()) {
343 fst.getCurrent().oopsDo(oopVisitor, fst.getRegisterMap());
344 }
345 }
346
347 public boolean isInStack(Address a) {
348 if (Assert.ASSERTS_ENABLED) {
349 Assert.that(VM.getVM().isDebugging(), "Not yet implemented for non-debugging system");
350 }
351 Address highest = highestLock();
352 Address sp = lastSPDbg();
353 // Be robust
354 if ((highest == null) || (sp == null)) return false;
355 return (highest.greaterThanOrEqual(a) && sp.lessThanOrEqual(a));
356
357 // FIXME: should traverse MonitorArray/MonitorChunks as in VM
358 }
359
360 public Oop getCurrentParkBlocker() {
361 Oop threadObj = getThreadObj();
362 if (threadObj != null) {
363 return OopUtilities.threadOopGetParkBlocker(threadObj);
364 }
365 return null;
366 }
367
368 public void printInfoOn(PrintStream tty) {
369
370 tty.println("State: " + getThreadState().toString());
371 // Attempt to figure out the addresses covered by Java frames.
372 // NOTE: we should make this a method and let the Stackwalk panel use the result too.
373 //
374 sun.jvm.hotspot.runtime.Frame tmpFrame = getCurrentFrameGuess();
375 if (tmpFrame != null ) {
376 Address sp = tmpFrame.getSP();
377 Address maxSP = sp;
378 Address minSP = sp;
379 RegisterMap tmpMap = newRegisterMap(false);
380 while ((tmpFrame != null) && (!tmpFrame.isFirstFrame())) {
381 tmpFrame = tmpFrame.sender(tmpMap);
382 if (tmpFrame != null) {
383 sp = tmpFrame.getSP();
384 maxSP = AddressOps.max(maxSP, sp);
385 minSP = AddressOps.min(minSP, sp);
386 }
387 }
388 tty.println("Stack in use by Java: " + minSP + " .. " + maxSP);
389 } else {
390 tty.println("No Java frames present");
391 }
392 tty.println("Base of Stack: " + getBaseOfStackPointer());
393 tty.println("Last_Java_SP: " + getLastJavaSP());
394 tty.println("Last_Java_FP: " + getLastJavaFP());
395 tty.println("Last_Java_PC: " + getLastJavaPC());
396 // More stuff like saved_execption_pc, safepoint_state, ...
397 access.printInfoOn(addr, tty);
398
399 }
400
401 ///////////////////////////////
402 // //
403 // FIXME: add more accessors //
404 // //
405 ///////////////////////////////
406
407 //--------------------------------------------------------------------------------
408 // Internals only below this point
409 //
410
411 private Frame cookLastFrame(Frame fr) {
412 if (fr == null) {
413 return null;
414 }
415
416 Address pc = fr.getPC();
417
418 if (Assert.ASSERTS_ENABLED) {
419 if (pc == null) {
420 Assert.that(VM.getVM().isDebugging(), "must have PC");
421 }
422 }
423 return fr;
424 }
425
426 private Address lastSPDbg() {
427 return access.getLastSP(addr);
428 }
429
430 }