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