9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 package jdk.internal.vm;
26
27 import java.util.Arrays;
28 import java.util.stream.Stream;
29
30 /**
31 * Represents a snapshot of information about a Thread.
32 */
33 class ThreadSnapshot {
34 private static final StackTraceElement[] EMPTY_STACK = new StackTraceElement[0];
35 private static final ThreadLock[] EMPTY_LOCKS = new ThreadLock[0];
36
37 // filled by VM
38 private String name;
39 private int threadStatus;
40 private Thread carrierThread;
41 private StackTraceElement[] stackTrace;
42 // owned monitors
43 private ThreadLock[] locks;
44 // an object the thread is blocked/waiting on, converted to ThreadBlocker by ThreadSnapshot.of()
45 private int blockerTypeOrdinal;
46 private Object blockerObject;
47 // the owner of the blockerObject when the object is park blocker and is AbstractOwnableSynchronizer
48 private Thread parkBlockerOwner;
49
50 // set by ThreadSnapshot.of()
51 private ThreadBlocker blocker;
52
53 private ThreadSnapshot() {}
54
55 /**
56 * Take a snapshot of a Thread to get all information about the thread.
57 * Return null if a ThreadSnapshot is not created, for example if the
58 * thread has terminated.
59 * @throws UnsupportedOperationException if not supported by VM
60 */
61 static ThreadSnapshot of(Thread thread) {
62 ThreadSnapshot snapshot = create(thread);
63 if (snapshot == null) {
64 return null; // thread terminated
65 }
66 if (snapshot.stackTrace == null) {
67 snapshot.stackTrace = EMPTY_STACK;
68 }
69 if (snapshot.locks != null) {
70 Arrays.stream(snapshot.locks).forEach(ThreadLock::finishInit);
71 } else {
72 snapshot.locks = EMPTY_LOCKS;
73 }
74 if (snapshot.blockerObject != null) {
75 snapshot.blocker = new ThreadBlocker(snapshot.blockerTypeOrdinal,
76 snapshot.blockerObject,
77 snapshot.parkBlockerOwner);
78 snapshot.blockerObject = null; // release
79 snapshot.parkBlockerOwner = null;
80 }
81 return snapshot;
82 }
83
84 /**
85 * Returns the thread name.
86 */
87 String threadName() {
88 return name;
89 }
90
91 /**
92 * Returns the thread state.
93 */
94 Thread.State threadState() {
95 return jdk.internal.misc.VM.toThreadState(threadStatus);
96 }
97
98 /**
99 * Returns the thread stack trace.
100 */
101 StackTraceElement[] stackTrace() {
102 return stackTrace;
103 }
104
105 /**
106 * Returns the thread's parkBlocker.
107 */
108 Object parkBlocker() {
109 return getBlocker(BlockerLockType.PARK_BLOCKER);
110 }
111
112 /**
113 * Returns the owner of the parkBlocker if the parkBlocker is an AbstractOwnableSynchronizer.
114 */
115 Thread parkBlockerOwner() {
116 return (blocker != null && blocker.type == BlockerLockType.PARK_BLOCKER) ? blocker.owner : null;
117 }
118
119 /**
120 * Returns the object that the thread is blocked on.
121 * @throws IllegalStateException if not in the blocked state
214 return type;
215 }
216
217 Object lockObject() {
218 if (type == OwnedLockType.ELIMINATED) {
219 // we have no lock object, lock contains lock class
220 return null;
221 }
222 return obj;
223 }
224 }
225
226 private record ThreadBlocker(BlockerLockType type, Object obj, Thread owner) {
227 private static final BlockerLockType[] lockTypeValues = BlockerLockType.values(); // cache
228
229 ThreadBlocker(int typeOrdinal, Object obj, Thread owner) {
230 this(lockTypeValues[typeOrdinal], obj, owner);
231 }
232 }
233
234 private static native ThreadSnapshot create(Thread thread);
235 }
|
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25 package jdk.internal.vm;
26
27 import java.util.Arrays;
28 import java.util.stream.Stream;
29 import jdk.internal.access.JavaLangAccess;
30 import jdk.internal.access.SharedSecrets;
31
32 /**
33 * Represents a snapshot of information about a Thread.
34 */
35 public class ThreadSnapshot {
36 private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
37 private static final StackTraceElement[] EMPTY_STACK = new StackTraceElement[0];
38 private static final ThreadLock[] EMPTY_LOCKS = new ThreadLock[0];
39
40 // filled by VM
41 private String name;
42 private int threadStatus;
43 private Thread carrierThread;
44 private StackTraceElement[] stackTrace;
45 // owned monitors
46 private ThreadLock[] locks;
47 // an object the thread is blocked/waiting on, converted to ThreadBlocker by ThreadSnapshot.of()
48 private int blockerTypeOrdinal;
49 private Object blockerObject;
50 // the owner of the blockerObject when the object is park blocker and is AbstractOwnableSynchronizer
51 private Thread parkBlockerOwner;
52
53 // set by ThreadSnapshot.of()
54 private ThreadBlocker blocker;
55
56 private ThreadSnapshot() {}
57
58 /**
59 * Take a snapshot of a Thread to get all information about the thread.
60 * @param thread the thread
61 * @param includeMonitors true to include the blocked on and owned object monitors
62 * @return the snapshot or {@code null} if the thread is not alive
63 */
64 public static ThreadSnapshot of(Thread thread, boolean includeMonitors) {
65 ThreadSnapshot snapshot = create(thread, includeMonitors);
66 if (snapshot == null) {
67 return null; // thread not alive
68 }
69 if (snapshot.stackTrace == null) {
70 snapshot.stackTrace = EMPTY_STACK;
71 } else {
72 JLA.finishInit(snapshot.stackTrace);
73 }
74 if (snapshot.locks != null) {
75 Arrays.stream(snapshot.locks).forEach(ThreadLock::finishInit);
76 } else {
77 snapshot.locks = EMPTY_LOCKS;
78 }
79 if (snapshot.blockerObject != null) {
80 snapshot.blocker = new ThreadBlocker(snapshot.blockerTypeOrdinal,
81 snapshot.blockerObject,
82 snapshot.parkBlockerOwner);
83 snapshot.blockerObject = null; // release
84 snapshot.parkBlockerOwner = null;
85 }
86 return snapshot;
87 }
88
89 /**
90 * Returns the thread name.
91 */
92 String threadName() {
93 return name;
94 }
95
96 /**
97 * Returns the thread state.
98 */
99 Thread.State threadState() {
100 return jdk.internal.misc.VM.toThreadState(threadStatus);
101 }
102
103 /**
104 * Returns the thread stack trace.
105 */
106 public StackTraceElement[] stackTrace() {
107 return stackTrace;
108 }
109
110 /**
111 * Returns the thread's parkBlocker.
112 */
113 Object parkBlocker() {
114 return getBlocker(BlockerLockType.PARK_BLOCKER);
115 }
116
117 /**
118 * Returns the owner of the parkBlocker if the parkBlocker is an AbstractOwnableSynchronizer.
119 */
120 Thread parkBlockerOwner() {
121 return (blocker != null && blocker.type == BlockerLockType.PARK_BLOCKER) ? blocker.owner : null;
122 }
123
124 /**
125 * Returns the object that the thread is blocked on.
126 * @throws IllegalStateException if not in the blocked state
219 return type;
220 }
221
222 Object lockObject() {
223 if (type == OwnedLockType.ELIMINATED) {
224 // we have no lock object, lock contains lock class
225 return null;
226 }
227 return obj;
228 }
229 }
230
231 private record ThreadBlocker(BlockerLockType type, Object obj, Thread owner) {
232 private static final BlockerLockType[] lockTypeValues = BlockerLockType.values(); // cache
233
234 ThreadBlocker(int typeOrdinal, Object obj, Thread owner) {
235 this(lockTypeValues[typeOrdinal], obj, owner);
236 }
237 }
238
239 private static native ThreadSnapshot create(Thread thread, boolean includeMonitors);
240 }
|