Mercurial > hg > truffle
annotate agent/src/share/classes/sun/jvm/hotspot/oops/OopUtilities.java @ 3944:35c656d0b685
7090654: nightly failures after 7086585
Reviewed-by: kvn
author | never |
---|---|
date | Wed, 14 Sep 2011 13:57:32 -0700 |
parents | f6f3bb0ee072 |
children | cfa2c82f4c04 |
rev | line source |
---|---|
0 | 1 /* |
2376
c7f3d0b4570f
7017732: move static fields into Class to prepare for perm gen removal
never
parents:
1552
diff
changeset
|
2 * Copyright (c) 2000, 2011, 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; | |
57 // threadStatus field is new since 1.5 | |
58 private static IntField threadStatusField; | |
59 // parkBlocker field is new since 1.6 | |
60 private static OopField threadParkBlockerField; | |
61 | |
62 // possible values of java_lang_Thread::ThreadStatus | |
63 private static int THREAD_STATUS_NEW; | |
64 /* | |
65 Other enum constants are not needed as of now. Uncomment these as and when needed. | |
66 | |
67 private static int THREAD_STATUS_RUNNABLE; | |
68 private static int THREAD_STATUS_SLEEPING; | |
69 private static int THREAD_STATUS_IN_OBJECT_WAIT; | |
70 private static int THREAD_STATUS_IN_OBJECT_WAIT_TIMED; | |
71 private static int THREAD_STATUS_PARKED; | |
72 private static int THREAD_STATUS_PARKED_TIMED; | |
73 private static int THREAD_STATUS_BLOCKED_ON_MONITOR_ENTER; | |
74 private static int THREAD_STATUS_TERMINATED; | |
75 */ | |
76 | |
77 // java.util.concurrent.locks.AbstractOwnableSynchronizer fields | |
78 private static OopField absOwnSyncOwnerThreadField; | |
79 | |
80 static { | |
81 VM.registerVMInitializedObserver(new Observer() { | |
82 public void update(Observable o, Object data) { | |
83 initialize(VM.getVM().getTypeDataBase()); | |
84 } | |
85 }); | |
86 } | |
87 | |
88 private static synchronized void initialize(TypeDataBase db) { | |
89 // FIXME: don't need this observer; however, do need a VM resumed | |
90 // and suspended observer to refetch fields | |
91 } | |
92 | |
93 public static String charArrayToString(TypeArray charArray) { | |
94 if (charArray == null) { | |
95 return null; | |
96 } | |
97 return charArrayToString(charArray, 0, (int) charArray.getLength()); | |
98 } | |
99 | |
100 public static String charArrayToString(TypeArray charArray, int offset, int length) { | |
101 if (charArray == null) { | |
102 return null; | |
103 } | |
104 final int limit = offset + length; | |
105 if (Assert.ASSERTS_ENABLED) { | |
106 Assert.that(offset >= 0 && limit <= charArray.getLength(), "out of bounds"); | |
107 } | |
108 StringBuffer buf = new StringBuffer(length); | |
109 for (int i = offset; i < limit; i++) { | |
110 buf.append(charArray.getCharAt(i)); | |
111 } | |
112 return buf.toString(); | |
113 } | |
114 | |
3939 | 115 public static String escapeString(String s) { |
116 StringBuilder sb = null; | |
117 for (int index = 0; index < s.length(); index++) { | |
118 char value = s.charAt(index); | |
119 if (value >= 32 && value < 127 || value == '\'' || value == '\\') { | |
120 if (sb != null) { | |
121 sb.append(value); | |
122 } | |
123 } else { | |
124 if (sb == null) { | |
125 sb = new StringBuilder(s.length() * 2); | |
126 sb.append(s, 0, index); | |
127 } | |
128 sb.append("\\u"); | |
129 if (value < 0x10) sb.append("000"); | |
130 else if (value < 0x100) sb.append("00"); | |
131 else if (value < 0x1000) sb.append("0"); | |
132 sb.append(Integer.toHexString(value)); | |
133 } | |
134 } | |
135 if (sb != null) { | |
136 return sb.toString(); | |
137 } | |
138 return s; | |
139 } | |
140 | |
0 | 141 public static String stringOopToString(Oop stringOop) { |
142 if (offsetField == null) { | |
143 InstanceKlass k = (InstanceKlass) stringOop.getKlass(); | |
144 offsetField = (IntField) k.findField("offset", "I"); | |
145 countField = (IntField) k.findField("count", "I"); | |
146 valueField = (OopField) k.findField("value", "[C"); | |
147 if (Assert.ASSERTS_ENABLED) { | |
148 Assert.that(offsetField != null && | |
149 countField != null && | |
150 valueField != null, "must find all java.lang.String fields"); | |
151 } | |
152 } | |
153 return charArrayToString((TypeArray) valueField.getValue(stringOop), | |
154 offsetField.getValue(stringOop), | |
155 countField.getValue(stringOop)); | |
156 } | |
157 | |
3939 | 158 public static String stringOopToEscapedString(Oop stringOop) { |
159 return escapeString(stringOopToString(stringOop)); | |
160 } | |
161 | |
0 | 162 private static void initThreadGroupFields() { |
163 if (threadGroupParentField == null) { | |
164 SystemDictionary sysDict = VM.getVM().getSystemDictionary(); | |
165 InstanceKlass k = sysDict.getThreadGroupKlass(); | |
166 threadGroupParentField = (OopField) k.findField("parent", "Ljava/lang/ThreadGroup;"); | |
167 threadGroupNameField = (OopField) k.findField("name", "Ljava/lang/String;"); | |
168 threadGroupNThreadsField = (IntField) k.findField("nthreads", "I"); | |
169 threadGroupThreadsField = (OopField) k.findField("threads", "[Ljava/lang/Thread;"); | |
170 threadGroupNGroupsField = (IntField) k.findField("ngroups", "I"); | |
171 threadGroupGroupsField = (OopField) k.findField("groups", "[Ljava/lang/ThreadGroup;"); | |
172 if (Assert.ASSERTS_ENABLED) { | |
173 Assert.that(threadGroupParentField != null && | |
174 threadGroupNameField != null && | |
175 threadGroupNThreadsField != null && | |
176 threadGroupThreadsField != null && | |
177 threadGroupNGroupsField != null && | |
178 threadGroupGroupsField != null, "must find all java.lang.ThreadGroup fields"); | |
179 } | |
180 } | |
181 } | |
182 | |
183 public static Oop threadGroupOopGetParent(Oop threadGroupOop) { | |
184 initThreadGroupFields(); | |
185 return threadGroupParentField.getValue(threadGroupOop); | |
186 } | |
187 | |
188 public static String threadGroupOopGetName(Oop threadGroupOop) { | |
189 initThreadGroupFields(); | |
190 return stringOopToString(threadGroupNameField.getValue(threadGroupOop)); | |
191 } | |
192 | |
193 public static Oop[] threadGroupOopGetThreads(Oop threadGroupOop) { | |
194 initThreadGroupFields(); | |
195 int nthreads = threadGroupNThreadsField.getValue(threadGroupOop); | |
196 Oop[] result = new Oop[nthreads]; | |
197 ObjArray threads = (ObjArray) threadGroupThreadsField.getValue(threadGroupOop); | |
198 for (int i = 0; i < nthreads; i++) { | |
199 result[i] = threads.getObjAt(i); | |
200 } | |
201 return result; | |
202 } | |
203 | |
204 public static Oop[] threadGroupOopGetGroups(Oop threadGroupOop) { | |
205 initThreadGroupFields(); | |
206 int ngroups = threadGroupNGroupsField.getValue(threadGroupOop); | |
207 Oop[] result = new Oop[ngroups]; | |
208 ObjArray groups = (ObjArray) threadGroupGroupsField.getValue(threadGroupOop); | |
209 for (int i = 0; i < ngroups; i++) { | |
210 result[i] = groups.getObjAt(i); | |
211 } | |
212 return result; | |
213 } | |
214 | |
215 private static void initThreadFields() { | |
216 if (threadNameField == null) { | |
217 SystemDictionary sysDict = VM.getVM().getSystemDictionary(); | |
218 InstanceKlass k = sysDict.getThreadKlass(); | |
219 threadNameField = (OopField) k.findField("name", "[C"); | |
220 threadGroupField = (OopField) k.findField("group", "Ljava/lang/ThreadGroup;"); | |
221 threadEETopField = (LongField) k.findField("eetop", "J"); | |
222 threadStatusField = (IntField) k.findField("threadStatus", "I"); | |
223 threadParkBlockerField = (OopField) k.findField("parkBlocker", | |
224 "Ljava/lang/Object;"); | |
225 TypeDataBase db = VM.getVM().getTypeDataBase(); | |
226 THREAD_STATUS_NEW = db.lookupIntConstant("java_lang_Thread::NEW").intValue(); | |
227 /* | |
228 Other enum constants are not needed as of now. Uncomment these as and when needed. | |
229 | |
230 THREAD_STATUS_RUNNABLE = db.lookupIntConstant("java_lang_Thread::RUNNABLE").intValue(); | |
231 THREAD_STATUS_SLEEPING = db.lookupIntConstant("java_lang_Thread::SLEEPING").intValue(); | |
232 THREAD_STATUS_IN_OBJECT_WAIT = db.lookupIntConstant("java_lang_Thread::IN_OBJECT_WAIT").intValue(); | |
233 THREAD_STATUS_IN_OBJECT_WAIT_TIMED = db.lookupIntConstant("java_lang_Thread::IN_OBJECT_WAIT_TIMED").intValue(); | |
234 THREAD_STATUS_PARKED = db.lookupIntConstant("java_lang_Thread::PARKED").intValue(); | |
235 THREAD_STATUS_PARKED_TIMED = db.lookupIntConstant("java_lang_Thread::PARKED_TIMED").intValue(); | |
236 THREAD_STATUS_BLOCKED_ON_MONITOR_ENTER = db.lookupIntConstant("java_lang_Thread::BLOCKED_ON_MONITOR_ENTER").intValue(); | |
237 THREAD_STATUS_TERMINATED = db.lookupIntConstant("java_lang_Thread::TERMINATED").intValue(); | |
238 */ | |
239 | |
240 if (Assert.ASSERTS_ENABLED) { | |
241 // it is okay to miss threadStatusField, because this was | |
242 // introduced only in 1.5 JDK. | |
243 Assert.that(threadNameField != null && | |
244 threadGroupField != null && | |
245 threadEETopField != null, "must find all java.lang.Thread fields"); | |
246 } | |
247 } | |
248 } | |
249 | |
250 public static Oop threadOopGetThreadGroup(Oop threadOop) { | |
251 initThreadFields(); | |
252 return threadGroupField.getValue(threadOop); | |
253 } | |
254 | |
255 public static String threadOopGetName(Oop threadOop) { | |
256 initThreadFields(); | |
257 return charArrayToString((TypeArray) threadNameField.getValue(threadOop)); | |
258 } | |
259 | |
260 /** May return null if, e.g., thread was not started */ | |
261 public static JavaThread threadOopGetJavaThread(Oop threadOop) { | |
262 initThreadFields(); | |
263 Address addr = threadOop.getHandle().getAddressAt(threadEETopField.getOffset()); | |
264 if (addr == null) { | |
265 return null; | |
266 } | |
267 return VM.getVM().getThreads().createJavaThreadWrapper(addr); | |
268 } | |
269 | |
270 /** returns value of java.lang.Thread.threadStatus field */ | |
271 public static int threadOopGetThreadStatus(Oop threadOop) { | |
272 initThreadFields(); | |
273 // The threadStatus is only present starting in 1.5 | |
274 if (threadStatusField != null) { | |
275 return (int) threadStatusField.getValue(threadOop); | |
276 } else { | |
277 // All we can easily figure out is if it is alive, but that is | |
278 // enough info for a valid unknown status. | |
279 JavaThread thr = threadOopGetJavaThread(threadOop); | |
280 if (thr == null) { | |
281 // the thread hasn't run yet or is in the process of exiting | |
282 return THREAD_STATUS_NEW; | |
283 } else { | |
284 return JVMTI_THREAD_STATE_ALIVE; | |
285 } | |
286 } | |
287 } | |
288 | |
289 /** returns value of java.lang.Thread.parkBlocker field */ | |
290 public static Oop threadOopGetParkBlocker(Oop threadOop) { | |
291 initThreadFields(); | |
292 if (threadParkBlockerField != null) { | |
293 return threadParkBlockerField.getValue(threadOop); | |
294 } | |
295 return null; | |
296 } | |
297 | |
298 // initialize fields for j.u.c.l AbstractOwnableSynchornizer class | |
299 private static void initAbsOwnSyncFields() { | |
300 if (absOwnSyncOwnerThreadField == null) { | |
301 SystemDictionary sysDict = VM.getVM().getSystemDictionary(); | |
302 InstanceKlass k = sysDict.getAbstractOwnableSynchronizerKlass(); | |
303 absOwnSyncOwnerThreadField = | |
304 (OopField) k.findField("exclusiveOwnerThread", | |
305 "Ljava/lang/Thread;"); | |
306 } | |
307 } | |
308 | |
309 // return exclusiveOwnerThread field of AbstractOwnableSynchronizer class | |
310 public static Oop abstractOwnableSynchronizerGetOwnerThread(Oop oop) { | |
311 initAbsOwnSyncFields(); | |
312 if (absOwnSyncOwnerThreadField == null) { | |
313 return null; // pre-1.6 VM? | |
314 } else { | |
315 return absOwnSyncOwnerThreadField.getValue(oop); | |
316 } | |
317 } | |
318 } |