Mercurial > hg > truffle
annotate agent/src/share/classes/sun/jvm/hotspot/oops/OopUtilities.java @ 6972:bd7a7ce2e264
6830717: replay of compilations would help with debugging
Summary: When java process crashed in compiler thread, repeat the compilation process will help finding root cause. This is done with using SA dump application class data and replay data from core dump, then use debug version of jvm to recompile the problematic java method.
Reviewed-by: kvn, twisti, sspitsyn
Contributed-by: yumin.qi@oracle.com
author | minqi |
---|---|
date | Mon, 12 Nov 2012 14:03:53 -0800 |
parents | cfa2c82f4c04 |
children |
rev | line source |
---|---|
0 | 1 /* |
6169
cfa2c82f4c04
7175133: jinfo failed to get system properties after 6924259
minqi
parents:
3939
diff
changeset
|
2 * Copyright (c) 2000, 2012, 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(); | |
6169
cfa2c82f4c04
7175133: jinfo failed to get system properties after 6924259
minqi
parents:
3939
diff
changeset
|
144 offsetField = (IntField) k.findField("offset", "I"); // optional |
cfa2c82f4c04
7175133: jinfo failed to get system properties after 6924259
minqi
parents:
3939
diff
changeset
|
145 countField = (IntField) k.findField("count", "I"); // optional |
0 | 146 valueField = (OopField) k.findField("value", "[C"); |
147 if (Assert.ASSERTS_ENABLED) { | |
6169
cfa2c82f4c04
7175133: jinfo failed to get system properties after 6924259
minqi
parents:
3939
diff
changeset
|
148 Assert.that(valueField != null, "Field \'value\' of java.lang.String not found"); |
0 | 149 } |
150 } | |
6169
cfa2c82f4c04
7175133: jinfo failed to get system properties after 6924259
minqi
parents:
3939
diff
changeset
|
151 if (offsetField != null && countField != null) { |
cfa2c82f4c04
7175133: jinfo failed to get system properties after 6924259
minqi
parents:
3939
diff
changeset
|
152 return charArrayToString((TypeArray) valueField.getValue(stringOop), |
cfa2c82f4c04
7175133: jinfo failed to get system properties after 6924259
minqi
parents:
3939
diff
changeset
|
153 offsetField.getValue(stringOop), |
cfa2c82f4c04
7175133: jinfo failed to get system properties after 6924259
minqi
parents:
3939
diff
changeset
|
154 countField.getValue(stringOop)); |
cfa2c82f4c04
7175133: jinfo failed to get system properties after 6924259
minqi
parents:
3939
diff
changeset
|
155 } |
cfa2c82f4c04
7175133: jinfo failed to get system properties after 6924259
minqi
parents:
3939
diff
changeset
|
156 return charArrayToString((TypeArray) valueField.getValue(stringOop)); |
0 | 157 } |
158 | |
3939 | 159 public static String stringOopToEscapedString(Oop stringOop) { |
160 return escapeString(stringOopToString(stringOop)); | |
161 } | |
162 | |
0 | 163 private static void initThreadGroupFields() { |
164 if (threadGroupParentField == null) { | |
165 SystemDictionary sysDict = VM.getVM().getSystemDictionary(); | |
166 InstanceKlass k = sysDict.getThreadGroupKlass(); | |
167 threadGroupParentField = (OopField) k.findField("parent", "Ljava/lang/ThreadGroup;"); | |
168 threadGroupNameField = (OopField) k.findField("name", "Ljava/lang/String;"); | |
169 threadGroupNThreadsField = (IntField) k.findField("nthreads", "I"); | |
170 threadGroupThreadsField = (OopField) k.findField("threads", "[Ljava/lang/Thread;"); | |
171 threadGroupNGroupsField = (IntField) k.findField("ngroups", "I"); | |
172 threadGroupGroupsField = (OopField) k.findField("groups", "[Ljava/lang/ThreadGroup;"); | |
173 if (Assert.ASSERTS_ENABLED) { | |
174 Assert.that(threadGroupParentField != null && | |
175 threadGroupNameField != null && | |
176 threadGroupNThreadsField != null && | |
177 threadGroupThreadsField != null && | |
178 threadGroupNGroupsField != null && | |
179 threadGroupGroupsField != null, "must find all java.lang.ThreadGroup fields"); | |
180 } | |
181 } | |
182 } | |
183 | |
184 public static Oop threadGroupOopGetParent(Oop threadGroupOop) { | |
185 initThreadGroupFields(); | |
186 return threadGroupParentField.getValue(threadGroupOop); | |
187 } | |
188 | |
189 public static String threadGroupOopGetName(Oop threadGroupOop) { | |
190 initThreadGroupFields(); | |
191 return stringOopToString(threadGroupNameField.getValue(threadGroupOop)); | |
192 } | |
193 | |
194 public static Oop[] threadGroupOopGetThreads(Oop threadGroupOop) { | |
195 initThreadGroupFields(); | |
196 int nthreads = threadGroupNThreadsField.getValue(threadGroupOop); | |
197 Oop[] result = new Oop[nthreads]; | |
198 ObjArray threads = (ObjArray) threadGroupThreadsField.getValue(threadGroupOop); | |
199 for (int i = 0; i < nthreads; i++) { | |
200 result[i] = threads.getObjAt(i); | |
201 } | |
202 return result; | |
203 } | |
204 | |
205 public static Oop[] threadGroupOopGetGroups(Oop threadGroupOop) { | |
206 initThreadGroupFields(); | |
207 int ngroups = threadGroupNGroupsField.getValue(threadGroupOop); | |
208 Oop[] result = new Oop[ngroups]; | |
209 ObjArray groups = (ObjArray) threadGroupGroupsField.getValue(threadGroupOop); | |
210 for (int i = 0; i < ngroups; i++) { | |
211 result[i] = groups.getObjAt(i); | |
212 } | |
213 return result; | |
214 } | |
215 | |
216 private static void initThreadFields() { | |
217 if (threadNameField == null) { | |
218 SystemDictionary sysDict = VM.getVM().getSystemDictionary(); | |
219 InstanceKlass k = sysDict.getThreadKlass(); | |
220 threadNameField = (OopField) k.findField("name", "[C"); | |
221 threadGroupField = (OopField) k.findField("group", "Ljava/lang/ThreadGroup;"); | |
222 threadEETopField = (LongField) k.findField("eetop", "J"); | |
223 threadStatusField = (IntField) k.findField("threadStatus", "I"); | |
224 threadParkBlockerField = (OopField) k.findField("parkBlocker", | |
225 "Ljava/lang/Object;"); | |
226 TypeDataBase db = VM.getVM().getTypeDataBase(); | |
227 THREAD_STATUS_NEW = db.lookupIntConstant("java_lang_Thread::NEW").intValue(); | |
228 /* | |
229 Other enum constants are not needed as of now. Uncomment these as and when needed. | |
230 | |
231 THREAD_STATUS_RUNNABLE = db.lookupIntConstant("java_lang_Thread::RUNNABLE").intValue(); | |
232 THREAD_STATUS_SLEEPING = db.lookupIntConstant("java_lang_Thread::SLEEPING").intValue(); | |
233 THREAD_STATUS_IN_OBJECT_WAIT = db.lookupIntConstant("java_lang_Thread::IN_OBJECT_WAIT").intValue(); | |
234 THREAD_STATUS_IN_OBJECT_WAIT_TIMED = db.lookupIntConstant("java_lang_Thread::IN_OBJECT_WAIT_TIMED").intValue(); | |
235 THREAD_STATUS_PARKED = db.lookupIntConstant("java_lang_Thread::PARKED").intValue(); | |
236 THREAD_STATUS_PARKED_TIMED = db.lookupIntConstant("java_lang_Thread::PARKED_TIMED").intValue(); | |
237 THREAD_STATUS_BLOCKED_ON_MONITOR_ENTER = db.lookupIntConstant("java_lang_Thread::BLOCKED_ON_MONITOR_ENTER").intValue(); | |
238 THREAD_STATUS_TERMINATED = db.lookupIntConstant("java_lang_Thread::TERMINATED").intValue(); | |
239 */ | |
240 | |
241 if (Assert.ASSERTS_ENABLED) { | |
242 // it is okay to miss threadStatusField, because this was | |
243 // introduced only in 1.5 JDK. | |
244 Assert.that(threadNameField != null && | |
245 threadGroupField != null && | |
246 threadEETopField != null, "must find all java.lang.Thread fields"); | |
247 } | |
248 } | |
249 } | |
250 | |
251 public static Oop threadOopGetThreadGroup(Oop threadOop) { | |
252 initThreadFields(); | |
253 return threadGroupField.getValue(threadOop); | |
254 } | |
255 | |
256 public static String threadOopGetName(Oop threadOop) { | |
257 initThreadFields(); | |
258 return charArrayToString((TypeArray) threadNameField.getValue(threadOop)); | |
259 } | |
260 | |
261 /** May return null if, e.g., thread was not started */ | |
262 public static JavaThread threadOopGetJavaThread(Oop threadOop) { | |
263 initThreadFields(); | |
264 Address addr = threadOop.getHandle().getAddressAt(threadEETopField.getOffset()); | |
265 if (addr == null) { | |
266 return null; | |
267 } | |
268 return VM.getVM().getThreads().createJavaThreadWrapper(addr); | |
269 } | |
270 | |
271 /** returns value of java.lang.Thread.threadStatus field */ | |
272 public static int threadOopGetThreadStatus(Oop threadOop) { | |
273 initThreadFields(); | |
274 // The threadStatus is only present starting in 1.5 | |
275 if (threadStatusField != null) { | |
276 return (int) threadStatusField.getValue(threadOop); | |
277 } else { | |
278 // All we can easily figure out is if it is alive, but that is | |
279 // enough info for a valid unknown status. | |
280 JavaThread thr = threadOopGetJavaThread(threadOop); | |
281 if (thr == null) { | |
282 // the thread hasn't run yet or is in the process of exiting | |
283 return THREAD_STATUS_NEW; | |
284 } else { | |
285 return JVMTI_THREAD_STATE_ALIVE; | |
286 } | |
287 } | |
288 } | |
289 | |
290 /** returns value of java.lang.Thread.parkBlocker field */ | |
291 public static Oop threadOopGetParkBlocker(Oop threadOop) { | |
292 initThreadFields(); | |
293 if (threadParkBlockerField != null) { | |
294 return threadParkBlockerField.getValue(threadOop); | |
295 } | |
296 return null; | |
297 } | |
298 | |
299 // initialize fields for j.u.c.l AbstractOwnableSynchornizer class | |
300 private static void initAbsOwnSyncFields() { | |
301 if (absOwnSyncOwnerThreadField == null) { | |
302 SystemDictionary sysDict = VM.getVM().getSystemDictionary(); | |
303 InstanceKlass k = sysDict.getAbstractOwnableSynchronizerKlass(); | |
304 absOwnSyncOwnerThreadField = | |
305 (OopField) k.findField("exclusiveOwnerThread", | |
306 "Ljava/lang/Thread;"); | |
307 } | |
308 } | |
309 | |
310 // return exclusiveOwnerThread field of AbstractOwnableSynchronizer class | |
311 public static Oop abstractOwnableSynchronizerGetOwnerThread(Oop oop) { | |
312 initAbsOwnSyncFields(); | |
313 if (absOwnSyncOwnerThreadField == null) { | |
314 return null; // pre-1.6 VM? | |
315 } else { | |
316 return absOwnSyncOwnerThreadField.getValue(oop); | |
317 } | |
318 } | |
319 } |