Mercurial > hg > truffle
annotate agent/src/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java @ 818:b109e761e927
6837472: com/sun/jdi/MonitorFrameInfo.java fails with AggressiveOpts in 6u14
Summary: Disable escape analysis when jvmti/debugger is used. Add support for EA ibto SA.
Reviewed-by: never
author | kvn |
---|---|
date | Tue, 09 Jun 2009 16:19:10 -0700 |
parents | d1605aabd0a1 |
children | c18cbe5936b8 |
rev | line source |
---|---|
0 | 1 /* |
196 | 2 * Copyright 2004-2008 Sun Microsystems, Inc. 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 * | |
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.utilities; | |
26 | |
27 import java.io.*; | |
28 import java.nio.channels.*; | |
29 import java.util.*; | |
30 import sun.jvm.hotspot.debugger.*; | |
31 import sun.jvm.hotspot.memory.*; | |
32 import sun.jvm.hotspot.oops.*; | |
33 import sun.jvm.hotspot.runtime.*; | |
34 | |
35 /* | |
36 * This class writes Java heap in hprof binary format. This format is | |
37 * used by Heap Analysis Tool (HAT). The class is heavily influenced | |
38 * by 'hprof_io.c' of 1.5 new hprof implementation. | |
39 */ | |
40 | |
41 /* hprof binary format: (result either written to a file or sent over | |
42 * the network). | |
43 * | |
44 * WARNING: This format is still under development, and is subject to | |
45 * change without notice. | |
46 * | |
47 * header "JAVA PROFILE 1.0.1" (0-terminated) | |
48 * u4 size of identifiers. Identifiers are used to represent | |
49 * UTF8 strings, objects, stack traces, etc. They usually | |
50 * have the same size as host pointers. For example, on | |
51 * Solaris and Win32, the size is 4. | |
52 * u4 high word | |
53 * u4 low word number of milliseconds since 0:00 GMT, 1/1/70 | |
54 * [record]* a sequence of records. | |
55 * | |
56 */ | |
57 | |
58 /* | |
59 * | |
60 * Record format: | |
61 * | |
62 * u1 a TAG denoting the type of the record | |
63 * u4 number of *microseconds* since the time stamp in the | |
64 * header. (wraps around in a little more than an hour) | |
65 * u4 number of bytes *remaining* in the record. Note that | |
66 * this number excludes the tag and the length field itself. | |
67 * [u1]* BODY of the record (a sequence of bytes) | |
68 */ | |
69 | |
70 /* | |
71 * The following TAGs are supported: | |
72 * | |
73 * TAG BODY notes | |
74 *---------------------------------------------------------- | |
75 * HPROF_UTF8 a UTF8-encoded name | |
76 * | |
77 * id name ID | |
78 * [u1]* UTF8 characters (no trailing zero) | |
79 * | |
80 * HPROF_LOAD_CLASS a newly loaded class | |
81 * | |
82 * u4 class serial number (> 0) | |
83 * id class object ID | |
84 * u4 stack trace serial number | |
85 * id class name ID | |
86 * | |
87 * HPROF_UNLOAD_CLASS an unloading class | |
88 * | |
89 * u4 class serial_number | |
90 * | |
91 * HPROF_FRAME a Java stack frame | |
92 * | |
93 * id stack frame ID | |
94 * id method name ID | |
95 * id method signature ID | |
96 * id source file name ID | |
97 * u4 class serial number | |
98 * i4 line number. >0: normal | |
99 * -1: unknown | |
100 * -2: compiled method | |
101 * -3: native method | |
102 * | |
103 * HPROF_TRACE a Java stack trace | |
104 * | |
105 * u4 stack trace serial number | |
106 * u4 thread serial number | |
107 * u4 number of frames | |
108 * [id]* stack frame IDs | |
109 * | |
110 * | |
111 * HPROF_ALLOC_SITES a set of heap allocation sites, obtained after GC | |
112 * | |
113 * u2 flags 0x0001: incremental vs. complete | |
114 * 0x0002: sorted by allocation vs. live | |
115 * 0x0004: whether to force a GC | |
116 * u4 cutoff ratio | |
117 * u4 total live bytes | |
118 * u4 total live instances | |
119 * u8 total bytes allocated | |
120 * u8 total instances allocated | |
121 * u4 number of sites that follow | |
122 * [u1 is_array: 0: normal object | |
123 * 2: object array | |
124 * 4: boolean array | |
125 * 5: char array | |
126 * 6: float array | |
127 * 7: double array | |
128 * 8: byte array | |
129 * 9: short array | |
130 * 10: int array | |
131 * 11: long array | |
132 * u4 class serial number (may be zero during startup) | |
133 * u4 stack trace serial number | |
134 * u4 number of bytes alive | |
135 * u4 number of instances alive | |
136 * u4 number of bytes allocated | |
137 * u4]* number of instance allocated | |
138 * | |
139 * HPROF_START_THREAD a newly started thread. | |
140 * | |
141 * u4 thread serial number (> 0) | |
142 * id thread object ID | |
143 * u4 stack trace serial number | |
144 * id thread name ID | |
145 * id thread group name ID | |
146 * id thread group parent name ID | |
147 * | |
148 * HPROF_END_THREAD a terminating thread. | |
149 * | |
150 * u4 thread serial number | |
151 * | |
152 * HPROF_HEAP_SUMMARY heap summary | |
153 * | |
154 * u4 total live bytes | |
155 * u4 total live instances | |
156 * u8 total bytes allocated | |
157 * u8 total instances allocated | |
158 * | |
159 * HPROF_HEAP_DUMP denote a heap dump | |
160 * | |
161 * [heap dump sub-records]* | |
162 * | |
163 * There are four kinds of heap dump sub-records: | |
164 * | |
165 * u1 sub-record type | |
166 * | |
167 * HPROF_GC_ROOT_UNKNOWN unknown root | |
168 * | |
169 * id object ID | |
170 * | |
171 * HPROF_GC_ROOT_THREAD_OBJ thread object | |
172 * | |
173 * id thread object ID (may be 0 for a | |
174 * thread newly attached through JNI) | |
175 * u4 thread sequence number | |
176 * u4 stack trace sequence number | |
177 * | |
178 * HPROF_GC_ROOT_JNI_GLOBAL JNI global ref root | |
179 * | |
180 * id object ID | |
181 * id JNI global ref ID | |
182 * | |
183 * HPROF_GC_ROOT_JNI_LOCAL JNI local ref | |
184 * | |
185 * id object ID | |
186 * u4 thread serial number | |
187 * u4 frame # in stack trace (-1 for empty) | |
188 * | |
189 * HPROF_GC_ROOT_JAVA_FRAME Java stack frame | |
190 * | |
191 * id object ID | |
192 * u4 thread serial number | |
193 * u4 frame # in stack trace (-1 for empty) | |
194 * | |
195 * HPROF_GC_ROOT_NATIVE_STACK Native stack | |
196 * | |
197 * id object ID | |
198 * u4 thread serial number | |
199 * | |
200 * HPROF_GC_ROOT_STICKY_CLASS System class | |
201 * | |
202 * id object ID | |
203 * | |
204 * HPROF_GC_ROOT_THREAD_BLOCK Reference from thread block | |
205 * | |
206 * id object ID | |
207 * u4 thread serial number | |
208 * | |
209 * HPROF_GC_ROOT_MONITOR_USED Busy monitor | |
210 * | |
211 * id object ID | |
212 * | |
213 * HPROF_GC_CLASS_DUMP dump of a class object | |
214 * | |
215 * id class object ID | |
216 * u4 stack trace serial number | |
217 * id super class object ID | |
218 * id class loader object ID | |
219 * id signers object ID | |
220 * id protection domain object ID | |
221 * id reserved | |
222 * id reserved | |
223 * | |
224 * u4 instance size (in bytes) | |
225 * | |
226 * u2 size of constant pool | |
227 * [u2, constant pool index, | |
228 * ty, type | |
229 * 2: object | |
230 * 4: boolean | |
231 * 5: char | |
232 * 6: float | |
233 * 7: double | |
234 * 8: byte | |
235 * 9: short | |
236 * 10: int | |
237 * 11: long | |
238 * vl]* and value | |
239 * | |
240 * u2 number of static fields | |
241 * [id, static field name, | |
242 * ty, type, | |
243 * vl]* and value | |
244 * | |
245 * u2 number of inst. fields (not inc. super) | |
246 * [id, instance field name, | |
247 * ty]* type | |
248 * | |
249 * HPROF_GC_INSTANCE_DUMP dump of a normal object | |
250 * | |
251 * id object ID | |
252 * u4 stack trace serial number | |
253 * id class object ID | |
254 * u4 number of bytes that follow | |
255 * [vl]* instance field values (class, followed | |
256 * by super, super's super ...) | |
257 * | |
258 * HPROF_GC_OBJ_ARRAY_DUMP dump of an object array | |
259 * | |
260 * id array object ID | |
261 * u4 stack trace serial number | |
262 * u4 number of elements | |
263 * id array class ID | |
264 * [id]* elements | |
265 * | |
266 * HPROF_GC_PRIM_ARRAY_DUMP dump of a primitive array | |
267 * | |
268 * id array object ID | |
269 * u4 stack trace serial number | |
270 * u4 number of elements | |
271 * u1 element type | |
272 * 4: boolean array | |
273 * 5: char array | |
274 * 6: float array | |
275 * 7: double array | |
276 * 8: byte array | |
277 * 9: short array | |
278 * 10: int array | |
279 * 11: long array | |
280 * [u1]* elements | |
281 * | |
282 * HPROF_CPU_SAMPLES a set of sample traces of running threads | |
283 * | |
284 * u4 total number of samples | |
285 * u4 # of traces | |
286 * [u4 # of samples | |
287 * u4]* stack trace serial number | |
288 * | |
289 * HPROF_CONTROL_SETTINGS the settings of on/off switches | |
290 * | |
291 * u4 0x00000001: alloc traces on/off | |
292 * 0x00000002: cpu sampling on/off | |
293 * u2 stack trace depth | |
294 * | |
295 */ | |
296 | |
297 public class HeapHprofBinWriter extends AbstractHeapGraphWriter { | |
298 // hprof binary file header | |
299 private static final String HPROF_HEADER = "JAVA PROFILE 1.0.1"; | |
300 | |
301 // constants in enum HprofTag | |
302 private static final int HPROF_UTF8 = 0x01; | |
303 private static final int HPROF_LOAD_CLASS = 0x02; | |
304 private static final int HPROF_UNLOAD_CLASS = 0x03; | |
305 private static final int HPROF_FRAME = 0x04; | |
306 private static final int HPROF_TRACE = 0x05; | |
307 private static final int HPROF_ALLOC_SITES = 0x06; | |
308 private static final int HPROF_HEAP_SUMMARY = 0x07; | |
309 private static final int HPROF_START_THREAD = 0x0A; | |
310 private static final int HPROF_END_THREAD = 0x0B; | |
311 private static final int HPROF_HEAP_DUMP = 0x0C; | |
312 private static final int HPROF_CPU_SAMPLES = 0x0D; | |
313 private static final int HPROF_CONTROL_SETTINGS = 0x0E; | |
314 | |
315 // Heap dump constants | |
316 // constants in enum HprofGcTag | |
317 private static final int HPROF_GC_ROOT_UNKNOWN = 0xFF; | |
318 private static final int HPROF_GC_ROOT_JNI_GLOBAL = 0x01; | |
319 private static final int HPROF_GC_ROOT_JNI_LOCAL = 0x02; | |
320 private static final int HPROF_GC_ROOT_JAVA_FRAME = 0x03; | |
321 private static final int HPROF_GC_ROOT_NATIVE_STACK = 0x04; | |
322 private static final int HPROF_GC_ROOT_STICKY_CLASS = 0x05; | |
323 private static final int HPROF_GC_ROOT_THREAD_BLOCK = 0x06; | |
324 private static final int HPROF_GC_ROOT_MONITOR_USED = 0x07; | |
325 private static final int HPROF_GC_ROOT_THREAD_OBJ = 0x08; | |
326 private static final int HPROF_GC_CLASS_DUMP = 0x20; | |
327 private static final int HPROF_GC_INSTANCE_DUMP = 0x21; | |
328 private static final int HPROF_GC_OBJ_ARRAY_DUMP = 0x22; | |
329 private static final int HPROF_GC_PRIM_ARRAY_DUMP = 0x23; | |
330 | |
331 // constants in enum HprofType | |
332 private static final int HPROF_ARRAY_OBJECT = 1; | |
333 private static final int HPROF_NORMAL_OBJECT = 2; | |
334 private static final int HPROF_BOOLEAN = 4; | |
335 private static final int HPROF_CHAR = 5; | |
336 private static final int HPROF_FLOAT = 6; | |
337 private static final int HPROF_DOUBLE = 7; | |
338 private static final int HPROF_BYTE = 8; | |
339 private static final int HPROF_SHORT = 9; | |
340 private static final int HPROF_INT = 10; | |
341 private static final int HPROF_LONG = 11; | |
342 | |
343 // Java type codes | |
344 private static final int JVM_SIGNATURE_BOOLEAN = 'Z'; | |
345 private static final int JVM_SIGNATURE_CHAR = 'C'; | |
346 private static final int JVM_SIGNATURE_BYTE = 'B'; | |
347 private static final int JVM_SIGNATURE_SHORT = 'S'; | |
348 private static final int JVM_SIGNATURE_INT = 'I'; | |
349 private static final int JVM_SIGNATURE_LONG = 'J'; | |
350 private static final int JVM_SIGNATURE_FLOAT = 'F'; | |
351 private static final int JVM_SIGNATURE_DOUBLE = 'D'; | |
352 private static final int JVM_SIGNATURE_ARRAY = '['; | |
353 private static final int JVM_SIGNATURE_CLASS = 'L'; | |
354 | |
355 | |
356 public synchronized void write(String fileName) throws IOException { | |
357 // open file stream and create buffered data output stream | |
358 FileOutputStream fos = new FileOutputStream(fileName); | |
359 FileChannel chn = fos.getChannel(); | |
360 out = new DataOutputStream(new BufferedOutputStream(fos)); | |
361 | |
362 VM vm = VM.getVM(); | |
363 dbg = vm.getDebugger(); | |
364 objectHeap = vm.getObjectHeap(); | |
365 symTbl = vm.getSymbolTable(); | |
366 | |
367 OBJ_ID_SIZE = (int) vm.getOopSize(); | |
368 | |
369 BOOLEAN_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_BOOLEAN); | |
370 BYTE_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_BYTE); | |
371 CHAR_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_CHAR); | |
372 SHORT_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_SHORT); | |
373 INT_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_INT); | |
374 LONG_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_LONG); | |
375 FLOAT_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_FLOAT); | |
376 DOUBLE_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_DOUBLE); | |
377 OBJECT_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_OBJECT); | |
378 | |
379 BOOLEAN_SIZE = objectHeap.getBooleanSize(); | |
380 BYTE_SIZE = objectHeap.getByteSize(); | |
381 CHAR_SIZE = objectHeap.getCharSize(); | |
382 SHORT_SIZE = objectHeap.getShortSize(); | |
383 INT_SIZE = objectHeap.getIntSize(); | |
384 LONG_SIZE = objectHeap.getLongSize(); | |
385 FLOAT_SIZE = objectHeap.getFloatSize(); | |
386 DOUBLE_SIZE = objectHeap.getDoubleSize(); | |
387 | |
388 // hprof bin format header | |
389 writeFileHeader(); | |
390 | |
391 // dummy stack trace without any frames so that | |
392 // HAT can be run without -stack false option | |
393 writeDummyTrace(); | |
394 | |
395 // hprof UTF-8 symbols section | |
396 writeSymbols(); | |
397 // HPROF_LOAD_CLASS records for all classes | |
398 writeClasses(); | |
399 | |
400 // write heap data now | |
401 out.writeByte((byte)HPROF_HEAP_DUMP); | |
402 out.writeInt(0); // relative timestamp | |
403 | |
404 // remember position of dump length, we will fixup | |
405 // length later - hprof format requires length. | |
406 out.flush(); | |
407 long dumpStart = chn.position(); | |
408 | |
409 // write dummy length of 0 and we'll fix it later. | |
410 out.writeInt(0); | |
411 | |
412 // write CLASS_DUMP records | |
413 writeClassDumpRecords(); | |
414 | |
415 // this will write heap data into the buffer stream | |
416 super.write(); | |
417 | |
418 // flush buffer stream and throw it. | |
419 out.flush(); | |
420 out = null; | |
421 | |
422 // now get current position to calculate length | |
423 long dumpEnd = chn.position(); | |
424 // calculate length of heap data | |
425 int dumpLen = (int) (dumpEnd - dumpStart - 4); | |
426 | |
427 // seek the position to write length | |
428 chn.position(dumpStart); | |
429 | |
430 // write length as integer | |
431 fos.write((dumpLen >>> 24) & 0xFF); | |
432 fos.write((dumpLen >>> 16) & 0xFF); | |
433 fos.write((dumpLen >>> 8) & 0xFF); | |
434 fos.write((dumpLen >>> 0) & 0xFF); | |
435 | |
436 // close the file stream | |
437 fos.close(); | |
438 } | |
439 | |
440 private void writeClassDumpRecords() throws IOException { | |
441 SystemDictionary sysDict = VM.getVM().getSystemDictionary(); | |
442 try { | |
443 sysDict.allClassesDo(new SystemDictionary.ClassVisitor() { | |
444 public void visit(Klass k) { | |
445 try { | |
446 writeClassDumpRecord(k); | |
447 } catch (IOException e) { | |
448 throw new RuntimeException(e); | |
449 } | |
450 } | |
451 }); | |
452 } catch (RuntimeException re) { | |
453 handleRuntimeException(re); | |
454 } | |
455 } | |
456 | |
457 protected void writeClass(Instance instance) throws IOException { | |
458 Klass reflectedKlass = OopUtilities.classOopToKlass(instance); | |
459 // dump instance record only for primitive type Class objects. | |
460 // all other Class objects are covered by writeClassDumpRecords. | |
461 if (reflectedKlass == null) { | |
462 writeInstance(instance); | |
463 } | |
464 } | |
465 | |
466 private void writeClassDumpRecord(Klass k) throws IOException { | |
467 out.writeByte((byte)HPROF_GC_CLASS_DUMP); | |
468 writeObjectID(k.getJavaMirror()); | |
469 out.writeInt(DUMMY_STACK_TRACE_ID); | |
470 Klass superKlass = k.getJavaSuper(); | |
471 if (superKlass != null) { | |
472 writeObjectID(superKlass.getJavaMirror()); | |
473 } else { | |
474 writeObjectID(null); | |
475 } | |
476 | |
477 if (k instanceof InstanceKlass) { | |
478 InstanceKlass ik = (InstanceKlass) k; | |
479 writeObjectID(ik.getClassLoader()); | |
480 writeObjectID(ik.getSigners()); | |
481 writeObjectID(ik.getProtectionDomain()); | |
482 // two reserved id fields | |
483 writeObjectID(null); | |
484 writeObjectID(null); | |
485 List fields = getInstanceFields(ik); | |
486 int instSize = getSizeForFields(fields); | |
487 classDataCache.put(ik, new ClassData(instSize, fields)); | |
488 out.writeInt(instSize); | |
489 | |
490 // For now, ignore constant pool - HAT ignores too! | |
491 // output number of cp entries as zero. | |
492 out.writeShort((short) 0); | |
493 | |
494 List declaredFields = ik.getImmediateFields(); | |
495 List staticFields = new ArrayList(); | |
496 List instanceFields = new ArrayList(); | |
497 Iterator itr = null; | |
498 for (itr = declaredFields.iterator(); itr.hasNext();) { | |
499 Field field = (Field) itr.next(); | |
500 if (field.isStatic()) { | |
501 staticFields.add(field); | |
502 } else { | |
503 instanceFields.add(field); | |
504 } | |
505 } | |
506 | |
507 // dump static field descriptors | |
508 writeFieldDescriptors(staticFields, ik); | |
509 | |
510 // dump instance field descriptors | |
511 writeFieldDescriptors(instanceFields, null); | |
512 } else { | |
513 if (k instanceof ObjArrayKlass) { | |
514 ObjArrayKlass oak = (ObjArrayKlass) k; | |
515 Klass bottomKlass = oak.getBottomKlass(); | |
516 if (bottomKlass instanceof InstanceKlass) { | |
517 InstanceKlass ik = (InstanceKlass) bottomKlass; | |
518 writeObjectID(ik.getClassLoader()); | |
519 writeObjectID(ik.getSigners()); | |
520 writeObjectID(ik.getProtectionDomain()); | |
521 } else { | |
522 writeObjectID(null); | |
523 writeObjectID(null); | |
524 writeObjectID(null); | |
525 } | |
526 } else { | |
527 writeObjectID(null); | |
528 writeObjectID(null); | |
529 writeObjectID(null); | |
530 } | |
531 // two reserved id fields | |
532 writeObjectID(null); | |
533 writeObjectID(null); | |
534 // write zero instance size -- as instance size | |
535 // is variable for arrays. | |
536 out.writeInt(0); | |
537 // no constant pool for array klasses | |
538 out.writeShort((short) 0); | |
539 // no static fields for array klasses | |
540 out.writeShort((short) 0); | |
541 // no instance fields for array klasses | |
542 out.writeShort((short) 0); | |
543 } | |
544 } | |
545 | |
546 protected void writeJavaThread(JavaThread jt, int index) throws IOException { | |
547 out.writeByte((byte) HPROF_GC_ROOT_THREAD_OBJ); | |
548 writeObjectID(jt.getThreadObj()); | |
549 out.writeInt(index); | |
550 out.writeInt(DUMMY_STACK_TRACE_ID); | |
551 writeLocalJNIHandles(jt, index); | |
552 } | |
553 | |
554 protected void writeLocalJNIHandles(JavaThread jt, int index) throws IOException { | |
555 final int threadIndex = index; | |
556 JNIHandleBlock blk = jt.activeHandles(); | |
557 if (blk != null) { | |
558 try { | |
559 blk.oopsDo(new AddressVisitor() { | |
560 public void visitAddress(Address handleAddr) { | |
561 try { | |
562 if (handleAddr != null) { | |
563 OopHandle oopHandle = handleAddr.getOopHandleAt(0); | |
564 Oop oop = objectHeap.newOop(oopHandle); | |
565 // exclude JNI handles hotspot internal objects | |
566 if (oop != null && isJavaVisible(oop)) { | |
567 out.writeByte((byte) HPROF_GC_ROOT_JNI_LOCAL); | |
568 writeObjectID(oop); | |
569 out.writeInt(threadIndex); | |
570 out.writeInt(EMPTY_FRAME_DEPTH); | |
571 } | |
572 } | |
573 } catch (IOException exp) { | |
574 throw new RuntimeException(exp); | |
575 } | |
576 } | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
577 public void visitCompOopAddress(Address handleAddr) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
578 throw new RuntimeException( |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
579 " Should not reach here. JNIHandles are not compressed \n"); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
580 } |
0 | 581 }); |
582 } catch (RuntimeException re) { | |
583 handleRuntimeException(re); | |
584 } | |
585 } | |
586 } | |
587 | |
588 protected void writeGlobalJNIHandle(Address handleAddr) throws IOException { | |
589 OopHandle oopHandle = handleAddr.getOopHandleAt(0); | |
590 Oop oop = objectHeap.newOop(oopHandle); | |
591 // exclude JNI handles of hotspot internal objects | |
592 if (oop != null && isJavaVisible(oop)) { | |
593 out.writeByte((byte) HPROF_GC_ROOT_JNI_GLOBAL); | |
594 writeObjectID(oop); | |
595 // use JNIHandle address as ID | |
596 writeObjectID(getAddressValue(handleAddr)); | |
597 } | |
598 } | |
599 | |
600 protected void writeObjectArray(ObjArray array) throws IOException { | |
601 out.writeByte((byte) HPROF_GC_OBJ_ARRAY_DUMP); | |
602 writeObjectID(array); | |
603 out.writeInt(DUMMY_STACK_TRACE_ID); | |
604 out.writeInt((int) array.getLength()); | |
605 writeObjectID(array.getKlass().getJavaMirror()); | |
606 final int length = (int) array.getLength(); | |
607 for (int index = 0; index < length; index++) { | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
608 OopHandle handle = array.getOopHandleAt(index); |
0 | 609 writeObjectID(getAddressValue(handle)); |
610 } | |
611 } | |
612 | |
613 protected void writePrimitiveArray(TypeArray array) throws IOException { | |
614 out.writeByte((byte) HPROF_GC_PRIM_ARRAY_DUMP); | |
615 writeObjectID(array); | |
616 out.writeInt(DUMMY_STACK_TRACE_ID); | |
617 out.writeInt((int) array.getLength()); | |
618 TypeArrayKlass tak = (TypeArrayKlass) array.getKlass(); | |
619 final int type = (int) tak.getElementType(); | |
620 out.writeByte((byte) type); | |
621 switch (type) { | |
622 case TypeArrayKlass.T_BOOLEAN: | |
623 writeBooleanArray(array); | |
624 break; | |
625 case TypeArrayKlass.T_CHAR: | |
626 writeCharArray(array); | |
627 break; | |
628 case TypeArrayKlass.T_FLOAT: | |
629 writeFloatArray(array); | |
630 break; | |
631 case TypeArrayKlass.T_DOUBLE: | |
632 writeDoubleArray(array); | |
633 break; | |
634 case TypeArrayKlass.T_BYTE: | |
635 writeByteArray(array); | |
636 break; | |
637 case TypeArrayKlass.T_SHORT: | |
638 writeShortArray(array); | |
639 break; | |
640 case TypeArrayKlass.T_INT: | |
641 writeIntArray(array); | |
642 break; | |
643 case TypeArrayKlass.T_LONG: | |
644 writeLongArray(array); | |
645 break; | |
646 default: | |
647 throw new RuntimeException("should not reach here"); | |
648 } | |
649 } | |
650 | |
651 private void writeBooleanArray(TypeArray array) throws IOException { | |
652 final int length = (int) array.getLength(); | |
653 for (int index = 0; index < length; index++) { | |
654 long offset = BOOLEAN_BASE_OFFSET + index * BOOLEAN_SIZE; | |
655 out.writeBoolean(array.getHandle().getJBooleanAt(offset)); | |
656 } | |
657 } | |
658 | |
659 private void writeByteArray(TypeArray array) throws IOException { | |
660 final int length = (int) array.getLength(); | |
661 for (int index = 0; index < length; index++) { | |
662 long offset = BYTE_BASE_OFFSET + index * BYTE_SIZE; | |
663 out.writeByte(array.getHandle().getJByteAt(offset)); | |
664 } | |
665 } | |
666 | |
667 private void writeShortArray(TypeArray array) throws IOException { | |
668 final int length = (int) array.getLength(); | |
669 for (int index = 0; index < length; index++) { | |
670 long offset = SHORT_BASE_OFFSET + index * SHORT_SIZE; | |
671 out.writeShort(array.getHandle().getJShortAt(offset)); | |
672 } | |
673 } | |
674 | |
675 private void writeIntArray(TypeArray array) throws IOException { | |
676 final int length = (int) array.getLength(); | |
677 for (int index = 0; index < length; index++) { | |
678 long offset = INT_BASE_OFFSET + index * INT_SIZE; | |
679 out.writeInt(array.getHandle().getJIntAt(offset)); | |
680 } | |
681 } | |
682 | |
683 private void writeLongArray(TypeArray array) throws IOException { | |
684 final int length = (int) array.getLength(); | |
685 for (int index = 0; index < length; index++) { | |
686 long offset = LONG_BASE_OFFSET + index * LONG_SIZE; | |
687 out.writeLong(array.getHandle().getJLongAt(offset)); | |
688 } | |
689 } | |
690 | |
691 private void writeCharArray(TypeArray array) throws IOException { | |
692 final int length = (int) array.getLength(); | |
693 for (int index = 0; index < length; index++) { | |
694 long offset = CHAR_BASE_OFFSET + index * CHAR_SIZE; | |
695 out.writeChar(array.getHandle().getJCharAt(offset)); | |
696 } | |
697 } | |
698 | |
699 private void writeFloatArray(TypeArray array) throws IOException { | |
700 final int length = (int) array.getLength(); | |
701 for (int index = 0; index < length; index++) { | |
702 long offset = FLOAT_BASE_OFFSET + index * FLOAT_SIZE; | |
703 out.writeFloat(array.getHandle().getJFloatAt(offset)); | |
704 } | |
705 } | |
706 | |
707 private void writeDoubleArray(TypeArray array) throws IOException { | |
708 final int length = (int) array.getLength(); | |
709 for (int index = 0; index < length; index++) { | |
710 long offset = DOUBLE_BASE_OFFSET + index * DOUBLE_SIZE; | |
711 out.writeDouble(array.getHandle().getJDoubleAt(offset)); | |
712 } | |
713 } | |
714 | |
715 protected void writeInstance(Instance instance) throws IOException { | |
716 out.writeByte((byte) HPROF_GC_INSTANCE_DUMP); | |
717 writeObjectID(instance); | |
718 out.writeInt(DUMMY_STACK_TRACE_ID); | |
719 Klass klass = instance.getKlass(); | |
720 writeObjectID(klass.getJavaMirror()); | |
721 | |
722 ClassData cd = (ClassData) classDataCache.get(klass); | |
723 if (Assert.ASSERTS_ENABLED) { | |
724 Assert.that(cd != null, "can not get class data for " + klass.getName().asString() + klass.getHandle()); | |
725 } | |
726 List fields = cd.fields; | |
727 int size = cd.instSize; | |
728 out.writeInt(size); | |
729 for (Iterator itr = fields.iterator(); itr.hasNext();) { | |
730 writeField((Field) itr.next(), instance); | |
731 } | |
732 } | |
733 | |
734 //-- Internals only below this point | |
735 | |
736 private void writeFieldDescriptors(List fields, InstanceKlass ik) | |
737 throws IOException { | |
738 // ik == null for instance fields. | |
739 out.writeShort((short) fields.size()); | |
740 for (Iterator itr = fields.iterator(); itr.hasNext();) { | |
741 Field field = (Field) itr.next(); | |
742 Symbol name = symTbl.probe(field.getID().getName()); | |
743 writeObjectID(name); | |
744 char typeCode = (char) field.getSignature().getByteAt(0); | |
745 int kind = signatureToHprofKind(typeCode); | |
746 out.writeByte((byte)kind); | |
747 if (ik != null) { | |
748 // static field | |
749 writeField(field, ik); | |
750 } | |
751 } | |
752 } | |
753 | |
754 public static int signatureToHprofKind(char ch) { | |
755 switch (ch) { | |
756 case JVM_SIGNATURE_CLASS: | |
757 case JVM_SIGNATURE_ARRAY: | |
758 return HPROF_NORMAL_OBJECT; | |
759 case JVM_SIGNATURE_BOOLEAN: | |
760 return HPROF_BOOLEAN; | |
761 case JVM_SIGNATURE_CHAR: | |
762 return HPROF_CHAR; | |
763 case JVM_SIGNATURE_FLOAT: | |
764 return HPROF_FLOAT; | |
765 case JVM_SIGNATURE_DOUBLE: | |
766 return HPROF_DOUBLE; | |
767 case JVM_SIGNATURE_BYTE: | |
768 return HPROF_BYTE; | |
769 case JVM_SIGNATURE_SHORT: | |
770 return HPROF_SHORT; | |
771 case JVM_SIGNATURE_INT: | |
772 return HPROF_INT; | |
773 case JVM_SIGNATURE_LONG: | |
774 return HPROF_LONG; | |
775 default: | |
776 throw new RuntimeException("should not reach here"); | |
777 } | |
778 } | |
779 | |
780 private void writeField(Field field, Oop oop) throws IOException { | |
781 char typeCode = (char) field.getSignature().getByteAt(0); | |
782 switch (typeCode) { | |
783 case JVM_SIGNATURE_BOOLEAN: | |
784 out.writeBoolean(((BooleanField)field).getValue(oop)); | |
785 break; | |
786 case JVM_SIGNATURE_CHAR: | |
787 out.writeChar(((CharField)field).getValue(oop)); | |
788 break; | |
789 case JVM_SIGNATURE_BYTE: | |
790 out.writeByte(((ByteField)field).getValue(oop)); | |
791 break; | |
792 case JVM_SIGNATURE_SHORT: | |
793 out.writeShort(((ShortField)field).getValue(oop)); | |
794 break; | |
795 case JVM_SIGNATURE_INT: | |
796 out.writeInt(((IntField)field).getValue(oop)); | |
797 break; | |
798 case JVM_SIGNATURE_LONG: | |
799 out.writeLong(((LongField)field).getValue(oop)); | |
800 break; | |
801 case JVM_SIGNATURE_FLOAT: | |
802 out.writeFloat(((FloatField)field).getValue(oop)); | |
803 break; | |
804 case JVM_SIGNATURE_DOUBLE: | |
805 out.writeDouble(((DoubleField)field).getValue(oop)); | |
806 break; | |
807 case JVM_SIGNATURE_CLASS: | |
808 case JVM_SIGNATURE_ARRAY: { | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
809 if (VM.getVM().isCompressedOopsEnabled()) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
810 OopHandle handle = ((NarrowOopField)field).getValueAsOopHandle(oop); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
811 writeObjectID(getAddressValue(handle)); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
812 } else { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
813 OopHandle handle = ((OopField)field).getValueAsOopHandle(oop); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
814 writeObjectID(getAddressValue(handle)); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
815 } |
0 | 816 break; |
817 } | |
818 default: | |
819 throw new RuntimeException("should not reach here"); | |
820 } | |
821 } | |
822 | |
823 private void writeHeader(int tag, int len) throws IOException { | |
824 out.writeByte((byte)tag); | |
825 out.writeInt(0); // current ticks | |
826 out.writeInt(len); | |
827 } | |
828 | |
829 private void writeDummyTrace() throws IOException { | |
830 writeHeader(HPROF_TRACE, 3 * 4); | |
831 out.writeInt(DUMMY_STACK_TRACE_ID); | |
832 out.writeInt(0); | |
833 out.writeInt(0); | |
834 } | |
835 | |
836 private void writeSymbols() throws IOException { | |
837 try { | |
838 symTbl.symbolsDo(new SymbolTable.SymbolVisitor() { | |
839 public void visit(Symbol sym) { | |
840 try { | |
841 writeSymbol(sym); | |
842 } catch (IOException exp) { | |
843 throw new RuntimeException(exp); | |
844 } | |
845 } | |
846 }); | |
847 } catch (RuntimeException re) { | |
848 handleRuntimeException(re); | |
849 } | |
850 } | |
851 | |
852 private void writeSymbol(Symbol sym) throws IOException { | |
853 byte[] buf = sym.asString().getBytes("UTF-8"); | |
854 writeHeader(HPROF_UTF8, buf.length + OBJ_ID_SIZE); | |
855 writeObjectID(sym); | |
856 out.write(buf); | |
857 } | |
858 | |
859 private void writeClasses() throws IOException { | |
860 // write class list (id, name) association | |
861 SystemDictionary sysDict = VM.getVM().getSystemDictionary(); | |
862 try { | |
863 sysDict.allClassesDo(new SystemDictionary.ClassVisitor() { | |
864 private int serialNum = 1; | |
865 public void visit(Klass k) { | |
866 try { | |
867 Instance clazz = k.getJavaMirror(); | |
868 writeHeader(HPROF_LOAD_CLASS, 2 * (OBJ_ID_SIZE + 4)); | |
869 out.writeInt(serialNum); | |
870 writeObjectID(clazz); | |
871 out.writeInt(DUMMY_STACK_TRACE_ID); | |
872 writeObjectID(k.getName()); | |
873 serialNum++; | |
874 } catch (IOException exp) { | |
875 throw new RuntimeException(exp); | |
876 } | |
877 } | |
878 }); | |
879 } catch (RuntimeException re) { | |
880 handleRuntimeException(re); | |
881 } | |
882 } | |
883 | |
884 // writes hprof binary file header | |
885 private void writeFileHeader() throws IOException { | |
886 // version string | |
887 out.writeBytes(HPROF_HEADER); | |
888 out.writeByte((byte)'\0'); | |
889 | |
890 // write identifier size. we use pointers as identifiers. | |
891 out.writeInt(OBJ_ID_SIZE); | |
892 | |
893 // timestamp -- file creation time. | |
894 out.writeLong(System.currentTimeMillis()); | |
895 } | |
896 | |
897 // writes unique ID for an object | |
898 private void writeObjectID(Oop oop) throws IOException { | |
899 OopHandle handle = (oop != null)? oop.getHandle() : null; | |
900 long address = getAddressValue(handle); | |
901 writeObjectID(address); | |
902 } | |
903 | |
904 private void writeObjectID(long address) throws IOException { | |
905 if (OBJ_ID_SIZE == 4) { | |
906 out.writeInt((int) address); | |
907 } else { | |
908 out.writeLong(address); | |
909 } | |
910 } | |
911 | |
912 private long getAddressValue(Address addr) { | |
913 return (addr == null)? 0L : dbg.getAddressValue(addr); | |
914 } | |
915 | |
916 // get all declared as well as inherited (directly/indirectly) fields | |
917 private static List/*<Field>*/ getInstanceFields(InstanceKlass ik) { | |
918 InstanceKlass klass = ik; | |
919 List res = new ArrayList(); | |
920 while (klass != null) { | |
921 List curFields = klass.getImmediateFields(); | |
922 for (Iterator itr = curFields.iterator(); itr.hasNext();) { | |
923 Field f = (Field) itr.next(); | |
924 if (! f.isStatic()) { | |
925 res.add(f); | |
926 } | |
927 } | |
928 klass = (InstanceKlass) klass.getSuper(); | |
929 } | |
930 return res; | |
931 } | |
932 | |
933 // get size in bytes (in stream) required for given fields. Note | |
934 // that this is not the same as object size in heap. The size in | |
935 // heap will include size of padding/alignment bytes as well. | |
936 private int getSizeForFields(List fields) { | |
937 int size = 0; | |
938 for (Iterator itr = fields.iterator(); itr.hasNext();) { | |
939 Field field = (Field) itr.next(); | |
940 char typeCode = (char) field.getSignature().getByteAt(0); | |
941 switch (typeCode) { | |
942 case JVM_SIGNATURE_BOOLEAN: | |
943 case JVM_SIGNATURE_BYTE: | |
944 size++; | |
945 break; | |
946 case JVM_SIGNATURE_CHAR: | |
947 case JVM_SIGNATURE_SHORT: | |
948 size += 2; | |
949 break; | |
950 case JVM_SIGNATURE_INT: | |
951 case JVM_SIGNATURE_FLOAT: | |
952 size += 4; | |
953 break; | |
954 case JVM_SIGNATURE_CLASS: | |
955 case JVM_SIGNATURE_ARRAY: | |
956 size += OBJ_ID_SIZE; | |
957 break; | |
958 case JVM_SIGNATURE_LONG: | |
959 case JVM_SIGNATURE_DOUBLE: | |
960 size += 8; | |
961 break; | |
962 default: | |
963 throw new RuntimeException("should not reach here"); | |
964 } | |
965 } | |
966 return size; | |
967 } | |
968 | |
969 // We don't have allocation site info. We write a dummy | |
970 // stack trace with this id. | |
971 private static final int DUMMY_STACK_TRACE_ID = 1; | |
972 private static final int EMPTY_FRAME_DEPTH = -1; | |
973 | |
974 private DataOutputStream out; | |
975 private Debugger dbg; | |
976 private ObjectHeap objectHeap; | |
977 private SymbolTable symTbl; | |
978 | |
979 // oopSize of the debuggee | |
980 private int OBJ_ID_SIZE; | |
981 | |
982 private long BOOLEAN_BASE_OFFSET; | |
983 private long BYTE_BASE_OFFSET; | |
984 private long CHAR_BASE_OFFSET; | |
985 private long SHORT_BASE_OFFSET; | |
986 private long INT_BASE_OFFSET; | |
987 private long LONG_BASE_OFFSET; | |
988 private long FLOAT_BASE_OFFSET; | |
989 private long DOUBLE_BASE_OFFSET; | |
990 private long OBJECT_BASE_OFFSET; | |
991 | |
992 private long BOOLEAN_SIZE; | |
993 private long BYTE_SIZE; | |
994 private long CHAR_SIZE; | |
995 private long SHORT_SIZE; | |
996 private long INT_SIZE; | |
997 private long LONG_SIZE; | |
998 private long FLOAT_SIZE; | |
999 private long DOUBLE_SIZE; | |
1000 | |
1001 private static class ClassData { | |
1002 int instSize; | |
1003 List fields; | |
1004 ClassData(int instSize, List fields) { | |
1005 this.instSize = instSize; | |
1006 this.fields = fields; | |
1007 } | |
1008 } | |
1009 | |
1010 private Map classDataCache = new HashMap(); // <InstanceKlass, ClassData> | |
1011 } |