Mercurial > hg > graal-compiler
annotate agent/src/share/classes/sun/jvm/hotspot/oops/OopUtilities.java @ 180:b9ebd46331d2
6710654: SAJDI failures with Compressed Oops
Summary: Use correct offset for the java.lang.Class _klass field in SA.
Reviewed-by: jrose, never
author | kvn |
---|---|
date | Wed, 04 Jun 2008 14:03:48 -0700 |
parents | ba764ed4b6f2 |
children | d1605aabd0a1 |
rev | line source |
---|---|
0 | 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.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.lang.Class fields | |
78 private static OopField hcKlassField; | |
79 | |
80 // java.util.concurrent.locks.AbstractOwnableSynchronizer fields | |
81 private static OopField absOwnSyncOwnerThreadField; | |
82 | |
83 static { | |
84 VM.registerVMInitializedObserver(new Observer() { | |
85 public void update(Observable o, Object data) { | |
86 initialize(VM.getVM().getTypeDataBase()); | |
87 } | |
88 }); | |
89 } | |
90 | |
91 private static synchronized void initialize(TypeDataBase db) { | |
92 // FIXME: don't need this observer; however, do need a VM resumed | |
93 // and suspended observer to refetch fields | |
94 } | |
95 | |
96 public static String charArrayToString(TypeArray charArray) { | |
97 if (charArray == null) { | |
98 return null; | |
99 } | |
100 return charArrayToString(charArray, 0, (int) charArray.getLength()); | |
101 } | |
102 | |
103 public static String charArrayToString(TypeArray charArray, int offset, int length) { | |
104 if (charArray == null) { | |
105 return null; | |
106 } | |
107 final int limit = offset + length; | |
108 if (Assert.ASSERTS_ENABLED) { | |
109 Assert.that(offset >= 0 && limit <= charArray.getLength(), "out of bounds"); | |
110 } | |
111 StringBuffer buf = new StringBuffer(length); | |
112 for (int i = offset; i < limit; i++) { | |
113 buf.append(charArray.getCharAt(i)); | |
114 } | |
115 return buf.toString(); | |
116 } | |
117 | |
118 public static String stringOopToString(Oop stringOop) { | |
119 if (offsetField == null) { | |
120 InstanceKlass k = (InstanceKlass) stringOop.getKlass(); | |
121 offsetField = (IntField) k.findField("offset", "I"); | |
122 countField = (IntField) k.findField("count", "I"); | |
123 valueField = (OopField) k.findField("value", "[C"); | |
124 if (Assert.ASSERTS_ENABLED) { | |
125 Assert.that(offsetField != null && | |
126 countField != null && | |
127 valueField != null, "must find all java.lang.String fields"); | |
128 } | |
129 } | |
130 return charArrayToString((TypeArray) valueField.getValue(stringOop), | |
131 offsetField.getValue(stringOop), | |
132 countField.getValue(stringOop)); | |
133 } | |
134 | |
135 private static void initThreadGroupFields() { | |
136 if (threadGroupParentField == null) { | |
137 SystemDictionary sysDict = VM.getVM().getSystemDictionary(); | |
138 InstanceKlass k = sysDict.getThreadGroupKlass(); | |
139 threadGroupParentField = (OopField) k.findField("parent", "Ljava/lang/ThreadGroup;"); | |
140 threadGroupNameField = (OopField) k.findField("name", "Ljava/lang/String;"); | |
141 threadGroupNThreadsField = (IntField) k.findField("nthreads", "I"); | |
142 threadGroupThreadsField = (OopField) k.findField("threads", "[Ljava/lang/Thread;"); | |
143 threadGroupNGroupsField = (IntField) k.findField("ngroups", "I"); | |
144 threadGroupGroupsField = (OopField) k.findField("groups", "[Ljava/lang/ThreadGroup;"); | |
145 if (Assert.ASSERTS_ENABLED) { | |
146 Assert.that(threadGroupParentField != null && | |
147 threadGroupNameField != null && | |
148 threadGroupNThreadsField != null && | |
149 threadGroupThreadsField != null && | |
150 threadGroupNGroupsField != null && | |
151 threadGroupGroupsField != null, "must find all java.lang.ThreadGroup fields"); | |
152 } | |
153 } | |
154 } | |
155 | |
156 public static Oop threadGroupOopGetParent(Oop threadGroupOop) { | |
157 initThreadGroupFields(); | |
158 return threadGroupParentField.getValue(threadGroupOop); | |
159 } | |
160 | |
161 public static String threadGroupOopGetName(Oop threadGroupOop) { | |
162 initThreadGroupFields(); | |
163 return stringOopToString(threadGroupNameField.getValue(threadGroupOop)); | |
164 } | |
165 | |
166 public static Oop[] threadGroupOopGetThreads(Oop threadGroupOop) { | |
167 initThreadGroupFields(); | |
168 int nthreads = threadGroupNThreadsField.getValue(threadGroupOop); | |
169 Oop[] result = new Oop[nthreads]; | |
170 ObjArray threads = (ObjArray) threadGroupThreadsField.getValue(threadGroupOop); | |
171 for (int i = 0; i < nthreads; i++) { | |
172 result[i] = threads.getObjAt(i); | |
173 } | |
174 return result; | |
175 } | |
176 | |
177 public static Oop[] threadGroupOopGetGroups(Oop threadGroupOop) { | |
178 initThreadGroupFields(); | |
179 int ngroups = threadGroupNGroupsField.getValue(threadGroupOop); | |
180 Oop[] result = new Oop[ngroups]; | |
181 ObjArray groups = (ObjArray) threadGroupGroupsField.getValue(threadGroupOop); | |
182 for (int i = 0; i < ngroups; i++) { | |
183 result[i] = groups.getObjAt(i); | |
184 } | |
185 return result; | |
186 } | |
187 | |
188 private static void initThreadFields() { | |
189 if (threadNameField == null) { | |
190 SystemDictionary sysDict = VM.getVM().getSystemDictionary(); | |
191 InstanceKlass k = sysDict.getThreadKlass(); | |
192 threadNameField = (OopField) k.findField("name", "[C"); | |
193 threadGroupField = (OopField) k.findField("group", "Ljava/lang/ThreadGroup;"); | |
194 threadEETopField = (LongField) k.findField("eetop", "J"); | |
195 threadStatusField = (IntField) k.findField("threadStatus", "I"); | |
196 threadParkBlockerField = (OopField) k.findField("parkBlocker", | |
197 "Ljava/lang/Object;"); | |
198 TypeDataBase db = VM.getVM().getTypeDataBase(); | |
199 THREAD_STATUS_NEW = db.lookupIntConstant("java_lang_Thread::NEW").intValue(); | |
200 /* | |
201 Other enum constants are not needed as of now. Uncomment these as and when needed. | |
202 | |
203 THREAD_STATUS_RUNNABLE = db.lookupIntConstant("java_lang_Thread::RUNNABLE").intValue(); | |
204 THREAD_STATUS_SLEEPING = db.lookupIntConstant("java_lang_Thread::SLEEPING").intValue(); | |
205 THREAD_STATUS_IN_OBJECT_WAIT = db.lookupIntConstant("java_lang_Thread::IN_OBJECT_WAIT").intValue(); | |
206 THREAD_STATUS_IN_OBJECT_WAIT_TIMED = db.lookupIntConstant("java_lang_Thread::IN_OBJECT_WAIT_TIMED").intValue(); | |
207 THREAD_STATUS_PARKED = db.lookupIntConstant("java_lang_Thread::PARKED").intValue(); | |
208 THREAD_STATUS_PARKED_TIMED = db.lookupIntConstant("java_lang_Thread::PARKED_TIMED").intValue(); | |
209 THREAD_STATUS_BLOCKED_ON_MONITOR_ENTER = db.lookupIntConstant("java_lang_Thread::BLOCKED_ON_MONITOR_ENTER").intValue(); | |
210 THREAD_STATUS_TERMINATED = db.lookupIntConstant("java_lang_Thread::TERMINATED").intValue(); | |
211 */ | |
212 | |
213 if (Assert.ASSERTS_ENABLED) { | |
214 // it is okay to miss threadStatusField, because this was | |
215 // introduced only in 1.5 JDK. | |
216 Assert.that(threadNameField != null && | |
217 threadGroupField != null && | |
218 threadEETopField != null, "must find all java.lang.Thread fields"); | |
219 } | |
220 } | |
221 } | |
222 | |
223 public static Oop threadOopGetThreadGroup(Oop threadOop) { | |
224 initThreadFields(); | |
225 return threadGroupField.getValue(threadOop); | |
226 } | |
227 | |
228 public static String threadOopGetName(Oop threadOop) { | |
229 initThreadFields(); | |
230 return charArrayToString((TypeArray) threadNameField.getValue(threadOop)); | |
231 } | |
232 | |
233 /** May return null if, e.g., thread was not started */ | |
234 public static JavaThread threadOopGetJavaThread(Oop threadOop) { | |
235 initThreadFields(); | |
236 Address addr = threadOop.getHandle().getAddressAt(threadEETopField.getOffset()); | |
237 if (addr == null) { | |
238 return null; | |
239 } | |
240 return VM.getVM().getThreads().createJavaThreadWrapper(addr); | |
241 } | |
242 | |
243 /** returns value of java.lang.Thread.threadStatus field */ | |
244 public static int threadOopGetThreadStatus(Oop threadOop) { | |
245 initThreadFields(); | |
246 // The threadStatus is only present starting in 1.5 | |
247 if (threadStatusField != null) { | |
248 return (int) threadStatusField.getValue(threadOop); | |
249 } else { | |
250 // All we can easily figure out is if it is alive, but that is | |
251 // enough info for a valid unknown status. | |
252 JavaThread thr = threadOopGetJavaThread(threadOop); | |
253 if (thr == null) { | |
254 // the thread hasn't run yet or is in the process of exiting | |
255 return THREAD_STATUS_NEW; | |
256 } else { | |
257 return JVMTI_THREAD_STATE_ALIVE; | |
258 } | |
259 } | |
260 } | |
261 | |
262 /** returns value of java.lang.Thread.parkBlocker field */ | |
263 public static Oop threadOopGetParkBlocker(Oop threadOop) { | |
264 initThreadFields(); | |
265 if (threadParkBlockerField != null) { | |
266 return threadParkBlockerField.getValue(threadOop); | |
267 } | |
268 return null; | |
269 } | |
270 | |
271 // initialize fields for java.lang.Class | |
272 private static void initClassFields() { | |
273 if (hcKlassField == null) { | |
274 // hc_klass is a HotSpot magic field and hence we can't | |
275 // find it from InstanceKlass for java.lang.Class. | |
276 TypeDataBase db = VM.getVM().getTypeDataBase(); | |
180 | 277 int hcKlassOffset = (int) Instance.getHeaderSize(); |
0 | 278 try { |
279 hcKlassOffset += (db.lookupIntConstant("java_lang_Class::hc_klass_offset").intValue() * | |
180 | 280 VM.getVM().getHeapOopSize()); |
0 | 281 } catch (RuntimeException re) { |
282 // ignore, currently java_lang_Class::hc_klass_offset is zero | |
283 } | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
284 if (VM.getVM().isCompressedOopsEnabled()) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
285 hcKlassField = new NarrowOopField(new NamedFieldIdentifier("hc_klass"), hcKlassOffset, true); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
286 } else { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
287 hcKlassField = new OopField(new NamedFieldIdentifier("hc_klass"), hcKlassOffset, true); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
288 } |
0 | 289 } |
290 } | |
291 | |
292 /** get klassOop field at offset hc_klass_offset from a java.lang.Class object */ | |
293 public static Klass classOopToKlass(Oop aClass) { | |
294 initClassFields(); | |
295 return (Klass) hcKlassField.getValue(aClass); | |
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 } |