Mercurial > hg > graal-jvmci-8
annotate agent/src/share/classes/sun/jvm/hotspot/oops/ObjectHeap.java @ 3972:4f93f0d00802
7059019: G1: add G1 support to the SA
Summary: Extend the SA to recognize the G1CollectedHeap and implement any code that's needed by our serviceability tools (jmap, jinfo, jstack, etc.) that depend on the SA.
Reviewed-by: never, poonam, johnc
author | tonyp |
---|---|
date | Tue, 20 Sep 2011 09:59:59 -0400 |
parents | 63997f575155 |
children | da91efe96a93 |
rev | line source |
---|---|
0 | 1 /* |
2411
63997f575155
7031614: jmap -permstat fails with java.lang.InternalError in sun.jvm.hotspot.oops.OopField.getValue
never
parents:
2177
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:
235
diff
changeset
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
c18cbe5936b8
6941466: Oracle rebranding changes for Hotspot repositories
trims
parents:
235
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:
235
diff
changeset
|
21 * questions. |
0 | 22 * |
23 */ | |
24 | |
25 // | |
26 // The ObjectHeap is an abstraction over all generations in the VM | |
27 // It gives access to all present objects and classes. | |
28 // | |
29 | |
30 package sun.jvm.hotspot.oops; | |
31 | |
32 import java.util.*; | |
33 | |
34 import sun.jvm.hotspot.debugger.*; | |
35 import sun.jvm.hotspot.gc_interface.*; | |
3972 | 36 import sun.jvm.hotspot.gc_implementation.g1.*; |
0 | 37 import sun.jvm.hotspot.gc_implementation.parallelScavenge.*; |
38 import sun.jvm.hotspot.memory.*; | |
39 import sun.jvm.hotspot.runtime.*; | |
40 import sun.jvm.hotspot.types.*; | |
41 import sun.jvm.hotspot.utilities.*; | |
42 | |
43 public class ObjectHeap { | |
44 | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
45 private static final boolean DEBUG; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
46 |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
47 static { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
48 DEBUG = System.getProperty("sun.jvm.hotspot.oops.ObjectHeap.DEBUG") != null; |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
49 } |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
50 |
0 | 51 private OopHandle methodKlassHandle; |
52 private OopHandle constMethodKlassHandle; | |
53 private OopHandle methodDataKlassHandle; | |
54 private OopHandle constantPoolKlassHandle; | |
55 private OopHandle constantPoolCacheKlassHandle; | |
56 private OopHandle klassKlassHandle; | |
57 private OopHandle instanceKlassKlassHandle; | |
58 private OopHandle typeArrayKlassKlassHandle; | |
59 private OopHandle objArrayKlassKlassHandle; | |
60 private OopHandle boolArrayKlassHandle; | |
61 private OopHandle byteArrayKlassHandle; | |
62 private OopHandle charArrayKlassHandle; | |
63 private OopHandle intArrayKlassHandle; | |
64 private OopHandle shortArrayKlassHandle; | |
65 private OopHandle longArrayKlassHandle; | |
66 private OopHandle singleArrayKlassHandle; | |
67 private OopHandle doubleArrayKlassHandle; | |
68 private OopHandle arrayKlassKlassHandle; | |
69 private OopHandle compiledICHolderKlassHandle; | |
70 | |
71 private MethodKlass methodKlassObj; | |
72 private ConstMethodKlass constMethodKlassObj; | |
73 private MethodDataKlass methodDataKlassObj; | |
74 private ConstantPoolKlass constantPoolKlassObj; | |
75 private ConstantPoolCacheKlass constantPoolCacheKlassObj; | |
76 private KlassKlass klassKlassObj; | |
77 private InstanceKlassKlass instanceKlassKlassObj; | |
78 private TypeArrayKlassKlass typeArrayKlassKlassObj; | |
79 private ObjArrayKlassKlass objArrayKlassKlassObj; | |
80 private TypeArrayKlass boolArrayKlassObj; | |
81 private TypeArrayKlass byteArrayKlassObj; | |
82 private TypeArrayKlass charArrayKlassObj; | |
83 private TypeArrayKlass intArrayKlassObj; | |
84 private TypeArrayKlass shortArrayKlassObj; | |
85 private TypeArrayKlass longArrayKlassObj; | |
86 private TypeArrayKlass singleArrayKlassObj; | |
87 private TypeArrayKlass doubleArrayKlassObj; | |
88 private ArrayKlassKlass arrayKlassKlassObj; | |
89 private CompiledICHolderKlass compiledICHolderKlassObj; | |
90 | |
91 public void initialize(TypeDataBase db) throws WrongTypeException { | |
92 // Lookup the roots in the object hierarchy. | |
93 Type universeType = db.lookupType("Universe"); | |
94 | |
95 methodKlassHandle = universeType.getOopField("_methodKlassObj").getValue(); | |
96 methodKlassObj = new MethodKlass(methodKlassHandle, this); | |
97 | |
98 constMethodKlassHandle = universeType.getOopField("_constMethodKlassObj").getValue(); | |
99 constMethodKlassObj = new ConstMethodKlass(constMethodKlassHandle, this); | |
100 | |
101 constantPoolKlassHandle = universeType.getOopField("_constantPoolKlassObj").getValue(); | |
102 constantPoolKlassObj = new ConstantPoolKlass(constantPoolKlassHandle, this); | |
103 | |
104 constantPoolCacheKlassHandle = universeType.getOopField("_constantPoolCacheKlassObj").getValue(); | |
105 constantPoolCacheKlassObj = new ConstantPoolCacheKlass(constantPoolCacheKlassHandle, this); | |
106 | |
107 klassKlassHandle = universeType.getOopField("_klassKlassObj").getValue(); | |
108 klassKlassObj = new KlassKlass(klassKlassHandle, this); | |
109 | |
110 arrayKlassKlassHandle = universeType.getOopField("_arrayKlassKlassObj").getValue(); | |
111 arrayKlassKlassObj = new ArrayKlassKlass(arrayKlassKlassHandle, this); | |
112 | |
113 instanceKlassKlassHandle = universeType.getOopField("_instanceKlassKlassObj").getValue(); | |
114 instanceKlassKlassObj = new InstanceKlassKlass(instanceKlassKlassHandle, this); | |
115 | |
116 typeArrayKlassKlassHandle = universeType.getOopField("_typeArrayKlassKlassObj").getValue(); | |
117 typeArrayKlassKlassObj = new TypeArrayKlassKlass(typeArrayKlassKlassHandle, this); | |
118 | |
119 objArrayKlassKlassHandle = universeType.getOopField("_objArrayKlassKlassObj").getValue(); | |
120 objArrayKlassKlassObj = new ObjArrayKlassKlass(objArrayKlassKlassHandle, this); | |
121 | |
122 boolArrayKlassHandle = universeType.getOopField("_boolArrayKlassObj").getValue(); | |
123 boolArrayKlassObj = new TypeArrayKlass(boolArrayKlassHandle, this); | |
124 | |
125 byteArrayKlassHandle = universeType.getOopField("_byteArrayKlassObj").getValue(); | |
126 byteArrayKlassObj = new TypeArrayKlass(byteArrayKlassHandle, this); | |
127 | |
128 charArrayKlassHandle = universeType.getOopField("_charArrayKlassObj").getValue(); | |
129 charArrayKlassObj = new TypeArrayKlass(charArrayKlassHandle, this); | |
130 | |
131 intArrayKlassHandle = universeType.getOopField("_intArrayKlassObj").getValue(); | |
132 intArrayKlassObj = new TypeArrayKlass(intArrayKlassHandle, this); | |
133 | |
134 shortArrayKlassHandle = universeType.getOopField("_shortArrayKlassObj").getValue(); | |
135 shortArrayKlassObj = new TypeArrayKlass(shortArrayKlassHandle, this); | |
136 | |
137 longArrayKlassHandle = universeType.getOopField("_longArrayKlassObj").getValue(); | |
138 longArrayKlassObj = new TypeArrayKlass(longArrayKlassHandle, this); | |
139 | |
140 singleArrayKlassHandle = universeType.getOopField("_singleArrayKlassObj").getValue(); | |
141 singleArrayKlassObj = new TypeArrayKlass(singleArrayKlassHandle, this); | |
142 | |
143 doubleArrayKlassHandle = universeType.getOopField("_doubleArrayKlassObj").getValue(); | |
144 doubleArrayKlassObj = new TypeArrayKlass(doubleArrayKlassHandle, this); | |
145 | |
146 if (!VM.getVM().isCore()) { | |
147 methodDataKlassHandle = universeType.getOopField("_methodDataKlassObj").getValue(); | |
148 methodDataKlassObj = new MethodDataKlass(methodDataKlassHandle, this); | |
149 | |
150 compiledICHolderKlassHandle = universeType.getOopField("_compiledICHolderKlassObj").getValue(); | |
151 compiledICHolderKlassObj= new CompiledICHolderKlass(compiledICHolderKlassHandle ,this); | |
152 } | |
153 } | |
154 | |
155 public ObjectHeap(TypeDataBase db) throws WrongTypeException { | |
156 // Get commonly used sizes of basic types | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
157 oopSize = VM.getVM().getOopSize(); |
0 | 158 byteSize = db.getJByteType().getSize(); |
159 charSize = db.getJCharType().getSize(); | |
160 booleanSize = db.getJBooleanType().getSize(); | |
161 intSize = db.getJIntType().getSize(); | |
162 shortSize = db.getJShortType().getSize(); | |
163 longSize = db.getJLongType().getSize(); | |
164 floatSize = db.getJFloatType().getSize(); | |
165 doubleSize = db.getJDoubleType().getSize(); | |
166 | |
167 initialize(db); | |
168 } | |
169 | |
170 /** Comparison operation for oops, either or both of which may be null */ | |
171 public boolean equal(Oop o1, Oop o2) { | |
172 if (o1 != null) return o1.equals(o2); | |
173 return (o2 == null); | |
174 } | |
175 | |
176 // Cached sizes of basic types | |
177 private long oopSize; | |
178 private long byteSize; | |
179 private long charSize; | |
180 private long booleanSize; | |
181 private long intSize; | |
182 private long shortSize; | |
183 private long longSize; | |
184 private long floatSize; | |
185 private long doubleSize; | |
186 | |
187 public long getOopSize() { return oopSize; } | |
188 public long getByteSize() { return byteSize; } | |
189 public long getCharSize() { return charSize; } | |
190 public long getBooleanSize() { return booleanSize; } | |
191 public long getIntSize() { return intSize; } | |
192 public long getShortSize() { return shortSize; } | |
193 public long getLongSize() { return longSize; } | |
194 public long getFloatSize() { return floatSize; } | |
195 public long getDoubleSize() { return doubleSize; } | |
196 | |
197 // Accessors for well-known system classes (from Universe) | |
198 public MethodKlass getMethodKlassObj() { return methodKlassObj; } | |
199 public ConstMethodKlass getConstMethodKlassObj() { return constMethodKlassObj; } | |
200 public MethodDataKlass getMethodDataKlassObj() { return methodDataKlassObj; } | |
201 public ConstantPoolKlass getConstantPoolKlassObj() { return constantPoolKlassObj; } | |
202 public ConstantPoolCacheKlass getConstantPoolCacheKlassObj() { return constantPoolCacheKlassObj; } | |
203 public KlassKlass getKlassKlassObj() { return klassKlassObj; } | |
204 public ArrayKlassKlass getArrayKlassKlassObj() { return arrayKlassKlassObj; } | |
205 public InstanceKlassKlass getInstanceKlassKlassObj() { return instanceKlassKlassObj; } | |
206 public ObjArrayKlassKlass getObjArrayKlassKlassObj() { return objArrayKlassKlassObj; } | |
207 public TypeArrayKlassKlass getTypeArrayKlassKlassObj() { return typeArrayKlassKlassObj; } | |
208 public TypeArrayKlass getBoolArrayKlassObj() { return boolArrayKlassObj; } | |
209 public TypeArrayKlass getByteArrayKlassObj() { return byteArrayKlassObj; } | |
210 public TypeArrayKlass getCharArrayKlassObj() { return charArrayKlassObj; } | |
211 public TypeArrayKlass getIntArrayKlassObj() { return intArrayKlassObj; } | |
212 public TypeArrayKlass getShortArrayKlassObj() { return shortArrayKlassObj; } | |
213 public TypeArrayKlass getLongArrayKlassObj() { return longArrayKlassObj; } | |
214 public TypeArrayKlass getSingleArrayKlassObj() { return singleArrayKlassObj; } | |
215 public TypeArrayKlass getDoubleArrayKlassObj() { return doubleArrayKlassObj; } | |
216 public CompiledICHolderKlass getCompiledICHolderKlassObj() { | |
217 if (Assert.ASSERTS_ENABLED) { | |
218 Assert.that(!VM.getVM().isCore(), "must not be called for core build"); | |
219 } | |
220 return compiledICHolderKlassObj; | |
221 } | |
222 | |
223 /** Takes a BasicType and returns the corresponding primitive array | |
224 klass */ | |
225 public Klass typeArrayKlassObj(int t) { | |
226 if (t == BasicType.getTBoolean()) return getBoolArrayKlassObj(); | |
227 if (t == BasicType.getTChar()) return getCharArrayKlassObj(); | |
228 if (t == BasicType.getTFloat()) return getSingleArrayKlassObj(); | |
229 if (t == BasicType.getTDouble()) return getDoubleArrayKlassObj(); | |
230 if (t == BasicType.getTByte()) return getByteArrayKlassObj(); | |
231 if (t == BasicType.getTShort()) return getShortArrayKlassObj(); | |
232 if (t == BasicType.getTInt()) return getIntArrayKlassObj(); | |
233 if (t == BasicType.getTLong()) return getLongArrayKlassObj(); | |
234 throw new RuntimeException("Illegal basic type " + t); | |
235 } | |
236 | |
237 /** an interface to filter objects while walking heap */ | |
238 public static interface ObjectFilter { | |
239 public boolean canInclude(Oop obj); | |
240 } | |
241 | |
242 /** The base heap iteration mechanism */ | |
243 public void iterate(HeapVisitor visitor) { | |
244 iterateLiveRegions(collectLiveRegions(), visitor, null); | |
245 } | |
246 | |
247 /** iterate objects satisfying a specified ObjectFilter */ | |
248 public void iterate(HeapVisitor visitor, ObjectFilter of) { | |
249 iterateLiveRegions(collectLiveRegions(), visitor, of); | |
250 } | |
251 | |
252 /** iterate objects of given Klass. param 'includeSubtypes' tells whether to | |
253 * include objects of subtypes or not */ | |
254 public void iterateObjectsOfKlass(HeapVisitor visitor, final Klass k, boolean includeSubtypes) { | |
255 if (includeSubtypes) { | |
256 if (k.isFinal()) { | |
257 // do the simpler "exact" klass loop | |
258 iterateExact(visitor, k); | |
259 } else { | |
260 iterateSubtypes(visitor, k); | |
261 } | |
262 } else { | |
263 // there can no object of abstract classes and interfaces | |
264 if (!k.isAbstract() && !k.isInterface()) { | |
265 iterateExact(visitor, k); | |
266 } | |
267 } | |
268 } | |
269 | |
270 /** iterate objects of given Klass (objects of subtypes included) */ | |
271 public void iterateObjectsOfKlass(HeapVisitor visitor, final Klass k) { | |
272 iterateObjectsOfKlass(visitor, k, true); | |
273 } | |
274 | |
275 /** This routine can be used to iterate through the heap at an | |
276 extremely low level (stepping word-by-word) to provide the | |
277 ability to do very low-level debugging */ | |
278 public void iterateRaw(RawHeapVisitor visitor) { | |
279 List liveRegions = collectLiveRegions(); | |
280 | |
281 // Summarize size | |
282 long totalSize = 0; | |
283 for (int i = 0; i < liveRegions.size(); i += 2) { | |
284 Address bottom = (Address) liveRegions.get(i); | |
285 Address top = (Address) liveRegions.get(i+1); | |
286 totalSize += top.minus(bottom); | |
287 } | |
288 visitor.prologue(totalSize); | |
289 | |
290 for (int i = 0; i < liveRegions.size(); i += 2) { | |
291 Address bottom = (Address) liveRegions.get(i); | |
292 Address top = (Address) liveRegions.get(i+1); | |
293 | |
294 // Traverses the space from bottom to top | |
295 while (bottom.lessThan(top)) { | |
296 visitor.visitAddress(bottom); | |
297 bottom = bottom.addOffsetTo(VM.getVM().getAddressSize()); | |
298 } | |
299 } | |
300 | |
301 visitor.epilogue(); | |
302 } | |
303 | |
304 // Iterates through only the perm generation for the purpose of | |
305 // finding static fields for liveness analysis | |
306 public void iteratePerm(HeapVisitor visitor) { | |
307 CollectedHeap heap = VM.getVM().getUniverse().heap(); | |
308 List liveRegions = new ArrayList(); | |
309 addPermGenLiveRegions(liveRegions, heap); | |
310 sortLiveRegions(liveRegions); | |
311 iterateLiveRegions(liveRegions, visitor, null); | |
312 } | |
313 | |
218
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
113
diff
changeset
|
314 public boolean isValidMethod(OopHandle handle) { |
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
113
diff
changeset
|
315 OopHandle klass = Oop.getKlassForOopHandle(handle); |
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
113
diff
changeset
|
316 if (klass != null && klass.equals(methodKlassHandle)) { |
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
113
diff
changeset
|
317 return true; |
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
113
diff
changeset
|
318 } |
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
113
diff
changeset
|
319 return false; |
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
113
diff
changeset
|
320 } |
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
113
diff
changeset
|
321 |
0 | 322 // Creates an instance from the Oop hierarchy based based on the handle |
323 public Oop newOop(OopHandle handle) { | |
324 // The only known way to detect the right type of an oop is | |
325 // traversing the class chain until a well-known klass is recognized. | |
326 // A more direct solution would require the klasses to expose | |
327 // the C++ vtbl structure. | |
328 | |
329 // Handle the null reference | |
330 if (handle == null) return null; | |
331 | |
332 // First check if handle is one of the root objects | |
333 if (handle.equals(methodKlassHandle)) return getMethodKlassObj(); | |
334 if (handle.equals(constMethodKlassHandle)) return getConstMethodKlassObj(); | |
335 if (handle.equals(constantPoolKlassHandle)) return getConstantPoolKlassObj(); | |
336 if (handle.equals(constantPoolCacheKlassHandle)) return getConstantPoolCacheKlassObj(); | |
337 if (handle.equals(instanceKlassKlassHandle)) return getInstanceKlassKlassObj(); | |
338 if (handle.equals(objArrayKlassKlassHandle)) return getObjArrayKlassKlassObj(); | |
339 if (handle.equals(klassKlassHandle)) return getKlassKlassObj(); | |
340 if (handle.equals(arrayKlassKlassHandle)) return getArrayKlassKlassObj(); | |
341 if (handle.equals(typeArrayKlassKlassHandle)) return getTypeArrayKlassKlassObj(); | |
342 if (handle.equals(boolArrayKlassHandle)) return getBoolArrayKlassObj(); | |
343 if (handle.equals(byteArrayKlassHandle)) return getByteArrayKlassObj(); | |
344 if (handle.equals(charArrayKlassHandle)) return getCharArrayKlassObj(); | |
345 if (handle.equals(intArrayKlassHandle)) return getIntArrayKlassObj(); | |
346 if (handle.equals(shortArrayKlassHandle)) return getShortArrayKlassObj(); | |
347 if (handle.equals(longArrayKlassHandle)) return getLongArrayKlassObj(); | |
348 if (handle.equals(singleArrayKlassHandle)) return getSingleArrayKlassObj(); | |
349 if (handle.equals(doubleArrayKlassHandle)) return getDoubleArrayKlassObj(); | |
350 if (!VM.getVM().isCore()) { | |
351 if (handle.equals(compiledICHolderKlassHandle)) return getCompiledICHolderKlassObj(); | |
352 if (handle.equals(methodDataKlassHandle)) return getMethodDataKlassObj(); | |
353 } | |
354 | |
355 // Then check if obj.klass() is one of the root objects | |
356 OopHandle klass = Oop.getKlassForOopHandle(handle); | |
357 if (klass != null) { | |
358 if (klass.equals(methodKlassHandle)) return new Method(handle, this); | |
359 if (klass.equals(constMethodKlassHandle)) return new ConstMethod(handle, this); | |
360 if (klass.equals(constantPoolKlassHandle)) return new ConstantPool(handle, this); | |
361 if (klass.equals(constantPoolCacheKlassHandle)) return new ConstantPoolCache(handle, this); | |
362 if (!VM.getVM().isCore()) { | |
363 if (klass.equals(compiledICHolderKlassHandle)) return new CompiledICHolder(handle, this); | |
364 if (klass.equals(methodDataKlassHandle)) return new MethodData(handle, this); | |
365 } | |
2411
63997f575155
7031614: jmap -permstat fails with java.lang.InternalError in sun.jvm.hotspot.oops.OopField.getValue
never
parents:
2177
diff
changeset
|
366 if (klass.equals(instanceKlassKlassHandle)) { |
63997f575155
7031614: jmap -permstat fails with java.lang.InternalError in sun.jvm.hotspot.oops.OopField.getValue
never
parents:
2177
diff
changeset
|
367 InstanceKlass ik = new InstanceKlass(handle, this); |
63997f575155
7031614: jmap -permstat fails with java.lang.InternalError in sun.jvm.hotspot.oops.OopField.getValue
never
parents:
2177
diff
changeset
|
368 if (ik.getName().asString().equals("java/lang/Class")) { |
63997f575155
7031614: jmap -permstat fails with java.lang.InternalError in sun.jvm.hotspot.oops.OopField.getValue
never
parents:
2177
diff
changeset
|
369 // We would normally do this using the vtable style |
63997f575155
7031614: jmap -permstat fails with java.lang.InternalError in sun.jvm.hotspot.oops.OopField.getValue
never
parents:
2177
diff
changeset
|
370 // lookup but since it's not used for these currently |
63997f575155
7031614: jmap -permstat fails with java.lang.InternalError in sun.jvm.hotspot.oops.OopField.getValue
never
parents:
2177
diff
changeset
|
371 // it's simpler to just check for the name. |
63997f575155
7031614: jmap -permstat fails with java.lang.InternalError in sun.jvm.hotspot.oops.OopField.getValue
never
parents:
2177
diff
changeset
|
372 return new InstanceMirrorKlass(handle, this); |
63997f575155
7031614: jmap -permstat fails with java.lang.InternalError in sun.jvm.hotspot.oops.OopField.getValue
never
parents:
2177
diff
changeset
|
373 } |
63997f575155
7031614: jmap -permstat fails with java.lang.InternalError in sun.jvm.hotspot.oops.OopField.getValue
never
parents:
2177
diff
changeset
|
374 return ik; |
63997f575155
7031614: jmap -permstat fails with java.lang.InternalError in sun.jvm.hotspot.oops.OopField.getValue
never
parents:
2177
diff
changeset
|
375 } |
0 | 376 if (klass.equals(objArrayKlassKlassHandle)) return new ObjArrayKlass(handle, this); |
377 if (klass.equals(typeArrayKlassKlassHandle)) return new TypeArrayKlass(handle, this); | |
378 | |
379 // Lastly check if obj.klass().klass() is on of the root objects | |
380 OopHandle klassKlass = Oop.getKlassForOopHandle(klass); | |
381 if (klassKlass != null) { | |
382 if (klassKlass.equals(instanceKlassKlassHandle)) return new Instance(handle, this); | |
383 if (klassKlass.equals(objArrayKlassKlassHandle)) return new ObjArray(handle, this); | |
384 if (klassKlass.equals(typeArrayKlassKlassHandle)) return new TypeArray(handle, this); | |
385 } | |
386 } | |
387 | |
218
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
113
diff
changeset
|
388 if (DEBUG) { |
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
113
diff
changeset
|
389 System.err.println("Unknown oop at " + handle); |
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
113
diff
changeset
|
390 System.err.println("Oop's klass is " + klass); |
a5838065ab24
6620329: jstack prints double native methods on Solaris/sparc
swamyv
parents:
113
diff
changeset
|
391 } |
0 | 392 |
393 throw new UnknownOopException(); | |
394 } | |
395 | |
396 // Print all objects in the object heap | |
397 public void print() { | |
398 HeapPrinter printer = new HeapPrinter(System.out); | |
399 iterate(printer); | |
400 } | |
401 | |
402 //--------------------------------------------------------------------------- | |
403 // Internals only below this point | |
404 // | |
405 | |
406 private void iterateExact(HeapVisitor visitor, final Klass k) { | |
407 iterateLiveRegions(collectLiveRegions(), visitor, new ObjectFilter() { | |
408 public boolean canInclude(Oop obj) { | |
409 Klass tk = obj.getKlass(); | |
410 // null Klass is seen sometimes! | |
411 return (tk != null && tk.equals(k)); | |
412 } | |
413 }); | |
414 } | |
415 | |
416 private void iterateSubtypes(HeapVisitor visitor, final Klass k) { | |
417 iterateLiveRegions(collectLiveRegions(), visitor, new ObjectFilter() { | |
418 public boolean canInclude(Oop obj) { | |
419 Klass tk = obj.getKlass(); | |
420 // null Klass is seen sometimes! | |
421 return (tk != null && tk.isSubtypeOf(k)); | |
422 } | |
423 }); | |
424 } | |
425 | |
426 private void iterateLiveRegions(List liveRegions, HeapVisitor visitor, ObjectFilter of) { | |
427 // Summarize size | |
428 long totalSize = 0; | |
429 for (int i = 0; i < liveRegions.size(); i += 2) { | |
430 Address bottom = (Address) liveRegions.get(i); | |
431 Address top = (Address) liveRegions.get(i+1); | |
432 totalSize += top.minus(bottom); | |
433 } | |
434 visitor.prologue(totalSize); | |
435 | |
436 CompactibleFreeListSpace cmsSpaceOld = null; | |
437 CompactibleFreeListSpace cmsSpacePerm = null; | |
438 CollectedHeap heap = VM.getVM().getUniverse().heap(); | |
439 | |
440 if (heap instanceof GenCollectedHeap) { | |
441 GenCollectedHeap genHeap = (GenCollectedHeap) heap; | |
442 Generation genOld = genHeap.getGen(1); | |
443 Generation genPerm = genHeap.permGen(); | |
444 if (genOld instanceof ConcurrentMarkSweepGeneration) { | |
445 ConcurrentMarkSweepGeneration concGen = (ConcurrentMarkSweepGeneration)genOld; | |
446 cmsSpaceOld = concGen.cmsSpace(); | |
447 } | |
448 if (genPerm instanceof ConcurrentMarkSweepGeneration) { | |
449 ConcurrentMarkSweepGeneration concGen = (ConcurrentMarkSweepGeneration)genPerm; | |
450 cmsSpacePerm = concGen.cmsSpace(); | |
451 } | |
452 } | |
453 | |
454 for (int i = 0; i < liveRegions.size(); i += 2) { | |
455 Address bottom = (Address) liveRegions.get(i); | |
456 Address top = (Address) liveRegions.get(i+1); | |
457 | |
458 try { | |
459 // Traverses the space from bottom to top | |
460 OopHandle handle = bottom.addOffsetToAsOopHandle(0); | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
461 |
0 | 462 while (handle.lessThan(top)) { |
463 Oop obj = null; | |
464 | |
465 try { | |
466 obj = newOop(handle); | |
467 } catch (UnknownOopException exp) { | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
468 if (DEBUG) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
469 throw new RuntimeException(" UnknownOopException " + exp); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
470 } |
0 | 471 } |
472 if (obj == null) { | |
473 //Find the object size using Printezis bits and skip over | |
474 System.err.println("Finding object size using Printezis bits and skipping over..."); | |
475 long size = 0; | |
476 | |
477 if ( (cmsSpaceOld != null) && cmsSpaceOld.contains(handle) ){ | |
478 size = cmsSpaceOld.collector().blockSizeUsingPrintezisBits(handle); | |
479 } else if ((cmsSpacePerm != null) && cmsSpacePerm.contains(handle) ){ | |
480 size = cmsSpacePerm.collector().blockSizeUsingPrintezisBits(handle); | |
481 } | |
482 | |
483 if (size <= 0) { | |
484 //Either Printezis bits not set or handle is not in cms space. | |
485 throw new UnknownOopException(); | |
486 } | |
487 | |
488 handle = handle.addOffsetToAsOopHandle(CompactibleFreeListSpace.adjustObjectSizeInBytes(size)); | |
489 continue; | |
490 } | |
491 if (of == null || of.canInclude(obj)) { | |
492 if (visitor.doObj(obj)) { | |
493 // doObj() returns true to abort this loop. | |
494 break; | |
495 } | |
496 } | |
497 if ( (cmsSpaceOld != null) && cmsSpaceOld.contains(handle) || | |
498 (cmsSpacePerm != null) && cmsSpacePerm.contains(handle) ) { | |
499 handle = handle.addOffsetToAsOopHandle(CompactibleFreeListSpace.adjustObjectSizeInBytes(obj.getObjectSize()) ); | |
500 } else { | |
501 handle = handle.addOffsetToAsOopHandle(obj.getObjectSize()); | |
502 } | |
503 } | |
504 } | |
505 catch (AddressException e) { | |
506 // This is okay at the top of these regions | |
507 } | |
508 catch (UnknownOopException e) { | |
509 // This is okay at the top of these regions | |
510 } | |
511 } | |
512 | |
513 visitor.epilogue(); | |
514 } | |
515 | |
516 private void addPermGenLiveRegions(List output, CollectedHeap heap) { | |
517 LiveRegionsCollector lrc = new LiveRegionsCollector(output); | |
3972 | 518 if (heap instanceof SharedHeap) { |
519 if (Assert.ASSERTS_ENABLED) { | |
520 Assert.that(heap instanceof GenCollectedHeap || | |
521 heap instanceof G1CollectedHeap, | |
522 "Expecting GenCollectedHeap or G1CollectedHeap, " + | |
523 "but got " + heap.getClass().getName()); | |
524 } | |
525 // Handles both GenCollectedHeap and G1CollectedHeap | |
526 SharedHeap sharedHeap = (SharedHeap) heap; | |
527 Generation gen = sharedHeap.permGen(); | |
0 | 528 gen.spaceIterate(lrc, true); |
529 } else if (heap instanceof ParallelScavengeHeap) { | |
530 ParallelScavengeHeap psh = (ParallelScavengeHeap) heap; | |
531 PSPermGen permGen = psh.permGen(); | |
532 addLiveRegions(permGen.objectSpace().getLiveRegions(), output); | |
533 } else { | |
534 if (Assert.ASSERTS_ENABLED) { | |
3972 | 535 Assert.that(false, |
536 "Expecting SharedHeap or ParallelScavengeHeap, " + | |
537 "but got " + heap.getClass().getName()); | |
0 | 538 } |
539 } | |
540 } | |
541 | |
542 private void addLiveRegions(List input, List output) { | |
543 for (Iterator itr = input.iterator(); itr.hasNext();) { | |
544 MemRegion reg = (MemRegion) itr.next(); | |
545 Address top = reg.end(); | |
546 Address bottom = reg.start(); | |
547 if (Assert.ASSERTS_ENABLED) { | |
548 Assert.that(top != null, "top address in a live region should not be null"); | |
549 } | |
550 if (Assert.ASSERTS_ENABLED) { | |
551 Assert.that(bottom != null, "bottom address in a live region should not be null"); | |
552 } | |
553 output.add(top); | |
554 output.add(bottom); | |
555 } | |
556 } | |
557 | |
558 private class LiveRegionsCollector implements SpaceClosure { | |
559 LiveRegionsCollector(List l) { | |
560 liveRegions = l; | |
561 } | |
562 | |
563 public void doSpace(Space s) { | |
564 addLiveRegions(s.getLiveRegions(), liveRegions); | |
565 } | |
566 private List liveRegions; | |
567 } | |
568 | |
569 // Returns a List<Address> where the addresses come in pairs. These | |
570 // designate the live regions of the heap. | |
571 private List collectLiveRegions() { | |
572 // We want to iterate through all live portions of the heap, but | |
573 // do not want to abort the heap traversal prematurely if we find | |
574 // a problem (like an allocated but uninitialized object at the | |
575 // top of a generation). To do this we enumerate all generations' | |
576 // bottom and top regions, and factor in TLABs if necessary. | |
577 | |
578 // List<Address>. Addresses come in pairs. | |
579 List liveRegions = new ArrayList(); | |
580 LiveRegionsCollector lrc = new LiveRegionsCollector(liveRegions); | |
581 | |
582 CollectedHeap heap = VM.getVM().getUniverse().heap(); | |
583 | |
584 if (heap instanceof GenCollectedHeap) { | |
585 GenCollectedHeap genHeap = (GenCollectedHeap) heap; | |
586 // Run through all generations, obtaining bottom-top pairs. | |
587 for (int i = 0; i < genHeap.nGens(); i++) { | |
588 Generation gen = genHeap.getGen(i); | |
589 gen.spaceIterate(lrc, true); | |
590 } | |
591 } else if (heap instanceof ParallelScavengeHeap) { | |
592 ParallelScavengeHeap psh = (ParallelScavengeHeap) heap; | |
593 PSYoungGen youngGen = psh.youngGen(); | |
594 // Add eden space | |
595 addLiveRegions(youngGen.edenSpace().getLiveRegions(), liveRegions); | |
596 // Add from-space but not to-space | |
597 addLiveRegions(youngGen.fromSpace().getLiveRegions(), liveRegions); | |
598 PSOldGen oldGen = psh.oldGen(); | |
599 addLiveRegions(oldGen.objectSpace().getLiveRegions(), liveRegions); | |
3972 | 600 } else if (heap instanceof G1CollectedHeap) { |
601 G1CollectedHeap g1h = (G1CollectedHeap) heap; | |
602 g1h.heapRegionIterate(lrc); | |
0 | 603 } else { |
604 if (Assert.ASSERTS_ENABLED) { | |
3972 | 605 Assert.that(false, "Expecting GenCollectedHeap, G1CollectedHeap, " + |
606 "or ParallelScavengeHeap, but got " + | |
607 heap.getClass().getName()); | |
0 | 608 } |
609 } | |
610 | |
611 // handle perm generation | |
612 addPermGenLiveRegions(liveRegions, heap); | |
613 | |
614 // If UseTLAB is enabled, snip out regions associated with TLABs' | |
615 // dead regions. Note that TLABs can be present in any generation. | |
616 | |
617 // FIXME: consider adding fewer boundaries to live region list. | |
618 // Theoretically only need to stop at TLAB's top and resume at its | |
619 // end. | |
620 | |
621 if (VM.getVM().getUseTLAB()) { | |
622 for (JavaThread thread = VM.getVM().getThreads().first(); thread != null; thread = thread.next()) { | |
623 if (thread.isJavaThread()) { | |
624 ThreadLocalAllocBuffer tlab = thread.tlab(); | |
625 if (tlab.start() != null) { | |
626 if ((tlab.top() == null) || (tlab.end() == null)) { | |
627 System.err.print("Warning: skipping invalid TLAB for thread "); | |
628 thread.printThreadIDOn(System.err); | |
629 System.err.println(); | |
630 } else { | |
631 // Go from: | |
632 // - below start() to start() | |
633 // - start() to top() | |
634 // - end() and above | |
635 liveRegions.add(tlab.start()); | |
636 liveRegions.add(tlab.start()); | |
637 liveRegions.add(tlab.top()); | |
638 liveRegions.add(tlab.end()); | |
639 } | |
640 } | |
641 } | |
642 } | |
643 } | |
644 | |
645 // Now sort live regions | |
646 sortLiveRegions(liveRegions); | |
647 | |
648 if (Assert.ASSERTS_ENABLED) { | |
649 Assert.that(liveRegions.size() % 2 == 0, "Must have even number of region boundaries"); | |
650 } | |
651 | |
652 return liveRegions; | |
653 } | |
654 | |
655 private void sortLiveRegions(List liveRegions) { | |
656 Collections.sort(liveRegions, new Comparator() { | |
657 public int compare(Object o1, Object o2) { | |
658 Address a1 = (Address) o1; | |
659 Address a2 = (Address) o2; | |
660 if (AddressOps.lt(a1, a2)) { | |
661 return -1; | |
662 } else if (AddressOps.gt(a1, a2)) { | |
663 return 1; | |
664 } | |
665 return 0; | |
666 } | |
667 }); | |
668 } | |
669 } |