Mercurial > hg > graal-jvmci-8
annotate agent/src/share/classes/sun/jvm/hotspot/oops/OopUtilities.java @ 24234:ea6f94ab283b default tip
Added tag jvmci-0.36 for changeset 8128b98d4736
author | Gilles Duboscq <gilles.m.duboscq@oracle.com> |
---|---|
date | Mon, 18 Sep 2017 18:49:45 +0200 |
parents | efe013052465 |
children |
rev | line source |
---|---|
0 | 1 /* |
23802 | 2 * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. |
0 | 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 * | |
1552
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
196
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
196
diff
changeset
|
20 * or visit www.oracle.com if you need additional information or have any |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
196
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 package sun.jvm.hotspot.oops; | |
26 | |
27 import java.util.*; | |
28 | |
29 import sun.jvm.hotspot.debugger.*; | |
30 import sun.jvm.hotspot.memory.*; | |
31 import sun.jvm.hotspot.runtime.*; | |
32 import sun.jvm.hotspot.types.TypeDataBase; | |
33 import sun.jvm.hotspot.utilities.*; | |
34 import sun.jvm.hotspot.jdi.JVMTIThreadState; | |
35 | |
36 /** A utility class encapsulating useful oop operations */ | |
37 | |
38 public class OopUtilities implements /* imports */ JVMTIThreadState { | |
39 | |
40 // FIXME: access should be synchronized and cleared when VM is | |
41 // resumed | |
42 // String fields | |
43 private static IntField offsetField; | |
44 private static IntField countField; | |
45 private static OopField valueField; | |
46 // ThreadGroup fields | |
47 private static OopField threadGroupParentField; | |
48 private static OopField threadGroupNameField; | |
49 private static IntField threadGroupNThreadsField; | |
50 private static OopField threadGroupThreadsField; | |
51 private static IntField threadGroupNGroupsField; | |
52 private static OopField threadGroupGroupsField; | |
53 // Thread fields | |
54 private static OopField threadNameField; | |
55 private static OopField threadGroupField; | |
56 private static LongField threadEETopField; | |
22841 | 57 //tid field is new since 1.5 |
58 private static LongField threadTIDField; | |
0 | 59 // threadStatus field is new since 1.5 |
60 private static IntField threadStatusField; | |
61 // parkBlocker field is new since 1.6 | |
62 private static OopField threadParkBlockerField; | |
63 | |
64 // possible values of java_lang_Thread::ThreadStatus | |
65 private static int THREAD_STATUS_NEW; | |
66 /* | |
67 Other enum constants are not needed as of now. Uncomment these as and when needed. | |
68 | |
69 private static int THREAD_STATUS_RUNNABLE; | |
70 private static int THREAD_STATUS_SLEEPING; | |
71 private static int THREAD_STATUS_IN_OBJECT_WAIT; | |
72 private static int THREAD_STATUS_IN_OBJECT_WAIT_TIMED; | |
73 private static int THREAD_STATUS_PARKED; | |
74 private static int THREAD_STATUS_PARKED_TIMED; | |
75 private static int THREAD_STATUS_BLOCKED_ON_MONITOR_ENTER; | |
76 private static int THREAD_STATUS_TERMINATED; | |
77 */ | |
78 | |
79 // java.util.concurrent.locks.AbstractOwnableSynchronizer fields | |
80 private static OopField absOwnSyncOwnerThreadField; | |
81 | |
82 static { | |
83 VM.registerVMInitializedObserver(new Observer() { | |
84 public void update(Observable o, Object data) { | |
85 initialize(VM.getVM().getTypeDataBase()); | |
86 } | |
87 }); | |
88 } | |
89 | |
90 private static synchronized void initialize(TypeDataBase db) { | |
91 // FIXME: don't need this observer; however, do need a VM resumed | |
92 // and suspended observer to refetch fields | |
93 } | |
94 | |
95 public static String charArrayToString(TypeArray charArray) { | |
96 if (charArray == null) { | |
97 return null; | |
98 } | |
99 return charArrayToString(charArray, 0, (int) charArray.getLength()); | |
100 } | |
101 | |
102 public static String charArrayToString(TypeArray charArray, int offset, int length) { | |
103 if (charArray == null) { | |
104 return null; | |
105 } | |
106 final int limit = offset + length; | |
107 if (Assert.ASSERTS_ENABLED) { | |
108 Assert.that(offset >= 0 && limit <= charArray.getLength(), "out of bounds"); | |
109 } | |
110 StringBuffer buf = new StringBuffer(length); | |
111 for (int i = offset; i < limit; i++) { | |
112 buf.append(charArray.getCharAt(i)); | |
113 } | |
114 return buf.toString(); | |
115 } | |
116 | |
3939 | 117 public static String escapeString(String s) { |
118 StringBuilder sb = null; | |
119 for (int index = 0; index < s.length(); index++) { | |
120 char value = s.charAt(index); | |
121 if (value >= 32 && value < 127 || value == '\'' || value == '\\') { | |
122 if (sb != null) { | |
123 sb.append(value); | |
124 } | |
125 } else { | |
126 if (sb == null) { | |
127 sb = new StringBuilder(s.length() * 2); | |
128 sb.append(s, 0, index); | |
129 } | |
130 sb.append("\\u"); | |
131 if (value < 0x10) sb.append("000"); | |
132 else if (value < 0x100) sb.append("00"); | |
133 else if (value < 0x1000) sb.append("0"); | |
134 sb.append(Integer.toHexString(value)); | |
135 } | |
136 } | |
137 if (sb != null) { | |
138 return sb.toString(); | |
139 } | |
140 return s; | |
141 } | |
142 | |
0 | 143 public static String stringOopToString(Oop stringOop) { |
144 if (offsetField == null) { | |
145 InstanceKlass k = (InstanceKlass) stringOop.getKlass(); | |
6169
cfa2c82f4c04
7175133: jinfo failed to get system properties after 6924259
minqi
parents:
3939
diff
changeset
|
146 offsetField = (IntField) k.findField("offset", "I"); // optional |
cfa2c82f4c04
7175133: jinfo failed to get system properties after 6924259
minqi
parents:
3939
diff
changeset
|
147 countField = (IntField) k.findField("count", "I"); // optional |
0 | 148 valueField = (OopField) k.findField("value", "[C"); |
149 if (Assert.ASSERTS_ENABLED) { | |
6169
cfa2c82f4c04
7175133: jinfo failed to get system properties after 6924259
minqi
parents:
3939
diff
changeset
|
150 Assert.that(valueField != null, "Field \'value\' of java.lang.String not found"); |
0 | 151 } |
152 } | |
6169
cfa2c82f4c04
7175133: jinfo failed to get system properties after 6924259
minqi
parents:
3939
diff
changeset
|
153 if (offsetField != null && countField != null) { |
cfa2c82f4c04
7175133: jinfo failed to get system properties after 6924259
minqi
parents:
3939
diff
changeset
|
154 return charArrayToString((TypeArray) valueField.getValue(stringOop), |
cfa2c82f4c04
7175133: jinfo failed to get system properties after 6924259
minqi
parents:
3939
diff
changeset
|
155 offsetField.getValue(stringOop), |
cfa2c82f4c04
7175133: jinfo failed to get system properties after 6924259
minqi
parents:
3939
diff
changeset
|
156 countField.getValue(stringOop)); |
cfa2c82f4c04
7175133: jinfo failed to get system properties after 6924259
minqi
parents:
3939
diff
changeset
|
157 } |
cfa2c82f4c04
7175133: jinfo failed to get system properties after 6924259
minqi
parents:
3939
diff
changeset
|
158 return charArrayToString((TypeArray) valueField.getValue(stringOop)); |
0 | 159 } |
160 | |
3939 | 161 public static String stringOopToEscapedString(Oop stringOop) { |
162 return escapeString(stringOopToString(stringOop)); | |
163 } | |
164 | |
0 | 165 private static void initThreadGroupFields() { |
166 if (threadGroupParentField == null) { | |
167 SystemDictionary sysDict = VM.getVM().getSystemDictionary(); | |
168 InstanceKlass k = sysDict.getThreadGroupKlass(); | |
169 threadGroupParentField = (OopField) k.findField("parent", "Ljava/lang/ThreadGroup;"); | |
170 threadGroupNameField = (OopField) k.findField("name", "Ljava/lang/String;"); | |
171 threadGroupNThreadsField = (IntField) k.findField("nthreads", "I"); | |
172 threadGroupThreadsField = (OopField) k.findField("threads", "[Ljava/lang/Thread;"); | |
173 threadGroupNGroupsField = (IntField) k.findField("ngroups", "I"); | |
174 threadGroupGroupsField = (OopField) k.findField("groups", "[Ljava/lang/ThreadGroup;"); | |
175 if (Assert.ASSERTS_ENABLED) { | |
176 Assert.that(threadGroupParentField != null && | |
177 threadGroupNameField != null && | |
178 threadGroupNThreadsField != null && | |
179 threadGroupThreadsField != null && | |
180 threadGroupNGroupsField != null && | |
181 threadGroupGroupsField != null, "must find all java.lang.ThreadGroup fields"); | |
182 } | |
183 } | |
184 } | |
185 | |
186 public static Oop threadGroupOopGetParent(Oop threadGroupOop) { | |
187 initThreadGroupFields(); | |
188 return threadGroupParentField.getValue(threadGroupOop); | |
189 } | |
190 | |
191 public static String threadGroupOopGetName(Oop threadGroupOop) { | |
192 initThreadGroupFields(); | |
193 return stringOopToString(threadGroupNameField.getValue(threadGroupOop)); | |
194 } | |
195 | |
196 public static Oop[] threadGroupOopGetThreads(Oop threadGroupOop) { | |
197 initThreadGroupFields(); | |
198 int nthreads = threadGroupNThreadsField.getValue(threadGroupOop); | |
199 Oop[] result = new Oop[nthreads]; | |
200 ObjArray threads = (ObjArray) threadGroupThreadsField.getValue(threadGroupOop); | |
201 for (int i = 0; i < nthreads; i++) { | |
202 result[i] = threads.getObjAt(i); | |
203 } | |
204 return result; | |
205 } | |
206 | |
207 public static Oop[] threadGroupOopGetGroups(Oop threadGroupOop) { | |
208 initThreadGroupFields(); | |
209 int ngroups = threadGroupNGroupsField.getValue(threadGroupOop); | |
210 Oop[] result = new Oop[ngroups]; | |
211 ObjArray groups = (ObjArray) threadGroupGroupsField.getValue(threadGroupOop); | |
212 for (int i = 0; i < ngroups; i++) { | |
213 result[i] = groups.getObjAt(i); | |
214 } | |
215 return result; | |
216 } | |
217 | |
218 private static void initThreadFields() { | |
219 if (threadNameField == null) { | |
220 SystemDictionary sysDict = VM.getVM().getSystemDictionary(); | |
221 InstanceKlass k = sysDict.getThreadKlass(); | |
23802 | 222 threadNameField = (OopField) k.findField("name", "Ljava/lang/String;"); |
0 | 223 threadGroupField = (OopField) k.findField("group", "Ljava/lang/ThreadGroup;"); |
224 threadEETopField = (LongField) k.findField("eetop", "J"); | |
22841 | 225 threadTIDField = (LongField) k.findField("tid", "J"); |
0 | 226 threadStatusField = (IntField) k.findField("threadStatus", "I"); |
227 threadParkBlockerField = (OopField) k.findField("parkBlocker", | |
228 "Ljava/lang/Object;"); | |
229 TypeDataBase db = VM.getVM().getTypeDataBase(); | |
230 THREAD_STATUS_NEW = db.lookupIntConstant("java_lang_Thread::NEW").intValue(); | |
231 /* | |
232 Other enum constants are not needed as of now. Uncomment these as and when needed. | |
233 | |
234 THREAD_STATUS_RUNNABLE = db.lookupIntConstant("java_lang_Thread::RUNNABLE").intValue(); | |
235 THREAD_STATUS_SLEEPING = db.lookupIntConstant("java_lang_Thread::SLEEPING").intValue(); | |
236 THREAD_STATUS_IN_OBJECT_WAIT = db.lookupIntConstant("java_lang_Thread::IN_OBJECT_WAIT").intValue(); | |
237 THREAD_STATUS_IN_OBJECT_WAIT_TIMED = db.lookupIntConstant("java_lang_Thread::IN_OBJECT_WAIT_TIMED").intValue(); | |
238 THREAD_STATUS_PARKED = db.lookupIntConstant("java_lang_Thread::PARKED").intValue(); | |
239 THREAD_STATUS_PARKED_TIMED = db.lookupIntConstant("java_lang_Thread::PARKED_TIMED").intValue(); | |
240 THREAD_STATUS_BLOCKED_ON_MONITOR_ENTER = db.lookupIntConstant("java_lang_Thread::BLOCKED_ON_MONITOR_ENTER").intValue(); | |
241 THREAD_STATUS_TERMINATED = db.lookupIntConstant("java_lang_Thread::TERMINATED").intValue(); | |
242 */ | |
243 | |
244 if (Assert.ASSERTS_ENABLED) { | |
245 // it is okay to miss threadStatusField, because this was | |
246 // introduced only in 1.5 JDK. | |
247 Assert.that(threadNameField != null && | |
248 threadGroupField != null && | |
249 threadEETopField != null, "must find all java.lang.Thread fields"); | |
250 } | |
251 } | |
252 } | |
253 | |
254 public static Oop threadOopGetThreadGroup(Oop threadOop) { | |
255 initThreadFields(); | |
256 return threadGroupField.getValue(threadOop); | |
257 } | |
258 | |
259 public static String threadOopGetName(Oop threadOop) { | |
260 initThreadFields(); | |
23802 | 261 return stringOopToString(threadNameField.getValue(threadOop)); |
0 | 262 } |
263 | |
264 /** May return null if, e.g., thread was not started */ | |
265 public static JavaThread threadOopGetJavaThread(Oop threadOop) { | |
266 initThreadFields(); | |
267 Address addr = threadOop.getHandle().getAddressAt(threadEETopField.getOffset()); | |
268 if (addr == null) { | |
269 return null; | |
270 } | |
271 return VM.getVM().getThreads().createJavaThreadWrapper(addr); | |
272 } | |
273 | |
22841 | 274 public static long threadOopGetTID(Oop threadOop) { |
275 initThreadFields(); | |
276 if (threadTIDField != null) { | |
277 return threadTIDField.getValue(threadOop); | |
278 } else { | |
279 return 0; | |
280 } | |
281 } | |
282 | |
0 | 283 /** returns value of java.lang.Thread.threadStatus field */ |
284 public static int threadOopGetThreadStatus(Oop threadOop) { | |
285 initThreadFields(); | |
286 // The threadStatus is only present starting in 1.5 | |
287 if (threadStatusField != null) { | |
288 return (int) threadStatusField.getValue(threadOop); | |
289 } else { | |
290 // All we can easily figure out is if it is alive, but that is | |
291 // enough info for a valid unknown status. | |
292 JavaThread thr = threadOopGetJavaThread(threadOop); | |
293 if (thr == null) { | |
294 // the thread hasn't run yet or is in the process of exiting | |
295 return THREAD_STATUS_NEW; | |
296 } else { | |
297 return JVMTI_THREAD_STATE_ALIVE; | |
298 } | |
299 } | |
300 } | |
301 | |
302 /** returns value of java.lang.Thread.parkBlocker field */ | |
303 public static Oop threadOopGetParkBlocker(Oop threadOop) { | |
304 initThreadFields(); | |
305 if (threadParkBlockerField != null) { | |
306 return threadParkBlockerField.getValue(threadOop); | |
307 } | |
308 return null; | |
309 } | |
310 | |
311 // initialize fields for j.u.c.l AbstractOwnableSynchornizer class | |
312 private static void initAbsOwnSyncFields() { | |
313 if (absOwnSyncOwnerThreadField == null) { | |
314 SystemDictionary sysDict = VM.getVM().getSystemDictionary(); | |
315 InstanceKlass k = sysDict.getAbstractOwnableSynchronizerKlass(); | |
316 absOwnSyncOwnerThreadField = | |
317 (OopField) k.findField("exclusiveOwnerThread", | |
318 "Ljava/lang/Thread;"); | |
319 } | |
320 } | |
321 | |
322 // return exclusiveOwnerThread field of AbstractOwnableSynchronizer class | |
323 public static Oop abstractOwnableSynchronizerGetOwnerThread(Oop oop) { | |
324 initAbsOwnSyncFields(); | |
325 if (absOwnSyncOwnerThreadField == null) { | |
326 return null; // pre-1.6 VM? | |
327 } else { | |
328 return absOwnSyncOwnerThreadField.getValue(oop); | |
329 } | |
330 } | |
331 } |