Mercurial > hg > truffle
annotate agent/src/share/classes/sun/jvm/hotspot/utilities/HeapHprofBinWriter.java @ 17736:58fc1b1523dc
8034079: G1: Refactor the HeapRegionSet hierarchy
Reviewed-by: tschatzl, pliden
author | brutisso |
---|---|
date | Fri, 14 Mar 2014 10:15:46 +0100 |
parents | 55fb97c4c58d |
children | 4ca6dc0799b6 |
rev | line source |
---|---|
0 | 1 /* |
17467
55fb97c4c58d
8029233: Update copyright year to match last edit in jdk8 hotspot repository for 2013
mikael
parents:
12820
diff
changeset
|
2 * Copyright (c) 2004, 2013, 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.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 * | |
12820
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
47 * header "JAVA PROFILE 1.0.1" or "JAVA PROFILE 1.0.2" (0-terminated) |
0 | 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 * | |
12820
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
295 * |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
296 * When the header is "JAVA PROFILE 1.0.2" a heap dump can optionally |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
297 * be generated as a sequence of heap dump segments. This sequence is |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
298 * terminated by an end record. The additional tags allowed by format |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
299 * "JAVA PROFILE 1.0.2" are: |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
300 * |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
301 * HPROF_HEAP_DUMP_SEGMENT denote a heap dump segment |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
302 * |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
303 * [heap dump sub-records]* |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
304 * The same sub-record types allowed by HPROF_HEAP_DUMP |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
305 * |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
306 * HPROF_HEAP_DUMP_END denotes the end of a heap dump |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
307 * |
0 | 308 */ |
309 | |
310 public class HeapHprofBinWriter extends AbstractHeapGraphWriter { | |
12820
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
311 |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
312 // The heap size threshold used to determine if segmented format |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
313 // ("JAVA PROFILE 1.0.2") should be used. |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
314 private static final long HPROF_SEGMENTED_HEAP_DUMP_THRESHOLD = 2L * 0x40000000; |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
315 |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
316 // The approximate size of a heap segment. Used to calculate when to create |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
317 // a new segment. |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
318 private static final long HPROF_SEGMENTED_HEAP_DUMP_SEGMENT_SIZE = 1L * 0x40000000; |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
319 |
0 | 320 // hprof binary file header |
12820
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
321 private static final String HPROF_HEADER_1_0_1 = "JAVA PROFILE 1.0.1"; |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
322 private static final String HPROF_HEADER_1_0_2 = "JAVA PROFILE 1.0.2"; |
0 | 323 |
324 // constants in enum HprofTag | |
325 private static final int HPROF_UTF8 = 0x01; | |
326 private static final int HPROF_LOAD_CLASS = 0x02; | |
327 private static final int HPROF_UNLOAD_CLASS = 0x03; | |
328 private static final int HPROF_FRAME = 0x04; | |
329 private static final int HPROF_TRACE = 0x05; | |
330 private static final int HPROF_ALLOC_SITES = 0x06; | |
331 private static final int HPROF_HEAP_SUMMARY = 0x07; | |
332 private static final int HPROF_START_THREAD = 0x0A; | |
333 private static final int HPROF_END_THREAD = 0x0B; | |
334 private static final int HPROF_HEAP_DUMP = 0x0C; | |
335 private static final int HPROF_CPU_SAMPLES = 0x0D; | |
336 private static final int HPROF_CONTROL_SETTINGS = 0x0E; | |
337 | |
12820
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
338 // 1.0.2 record types |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
339 private static final int HPROF_HEAP_DUMP_SEGMENT = 0x1C; |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
340 private static final int HPROF_HEAP_DUMP_END = 0x2C; |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
341 |
0 | 342 // Heap dump constants |
343 // constants in enum HprofGcTag | |
344 private static final int HPROF_GC_ROOT_UNKNOWN = 0xFF; | |
345 private static final int HPROF_GC_ROOT_JNI_GLOBAL = 0x01; | |
346 private static final int HPROF_GC_ROOT_JNI_LOCAL = 0x02; | |
347 private static final int HPROF_GC_ROOT_JAVA_FRAME = 0x03; | |
348 private static final int HPROF_GC_ROOT_NATIVE_STACK = 0x04; | |
349 private static final int HPROF_GC_ROOT_STICKY_CLASS = 0x05; | |
350 private static final int HPROF_GC_ROOT_THREAD_BLOCK = 0x06; | |
351 private static final int HPROF_GC_ROOT_MONITOR_USED = 0x07; | |
352 private static final int HPROF_GC_ROOT_THREAD_OBJ = 0x08; | |
353 private static final int HPROF_GC_CLASS_DUMP = 0x20; | |
354 private static final int HPROF_GC_INSTANCE_DUMP = 0x21; | |
355 private static final int HPROF_GC_OBJ_ARRAY_DUMP = 0x22; | |
356 private static final int HPROF_GC_PRIM_ARRAY_DUMP = 0x23; | |
357 | |
358 // constants in enum HprofType | |
359 private static final int HPROF_ARRAY_OBJECT = 1; | |
360 private static final int HPROF_NORMAL_OBJECT = 2; | |
361 private static final int HPROF_BOOLEAN = 4; | |
362 private static final int HPROF_CHAR = 5; | |
363 private static final int HPROF_FLOAT = 6; | |
364 private static final int HPROF_DOUBLE = 7; | |
365 private static final int HPROF_BYTE = 8; | |
366 private static final int HPROF_SHORT = 9; | |
367 private static final int HPROF_INT = 10; | |
368 private static final int HPROF_LONG = 11; | |
369 | |
370 // Java type codes | |
371 private static final int JVM_SIGNATURE_BOOLEAN = 'Z'; | |
372 private static final int JVM_SIGNATURE_CHAR = 'C'; | |
373 private static final int JVM_SIGNATURE_BYTE = 'B'; | |
374 private static final int JVM_SIGNATURE_SHORT = 'S'; | |
375 private static final int JVM_SIGNATURE_INT = 'I'; | |
376 private static final int JVM_SIGNATURE_LONG = 'J'; | |
377 private static final int JVM_SIGNATURE_FLOAT = 'F'; | |
378 private static final int JVM_SIGNATURE_DOUBLE = 'D'; | |
379 private static final int JVM_SIGNATURE_ARRAY = '['; | |
380 private static final int JVM_SIGNATURE_CLASS = 'L'; | |
381 | |
382 public synchronized void write(String fileName) throws IOException { | |
383 // open file stream and create buffered data output stream | |
12820
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
384 fos = new FileOutputStream(fileName); |
0 | 385 out = new DataOutputStream(new BufferedOutputStream(fos)); |
386 | |
387 VM vm = VM.getVM(); | |
388 dbg = vm.getDebugger(); | |
389 objectHeap = vm.getObjectHeap(); | |
390 symTbl = vm.getSymbolTable(); | |
391 | |
392 OBJ_ID_SIZE = (int) vm.getOopSize(); | |
393 | |
394 BOOLEAN_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_BOOLEAN); | |
395 BYTE_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_BYTE); | |
396 CHAR_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_CHAR); | |
397 SHORT_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_SHORT); | |
398 INT_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_INT); | |
399 LONG_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_LONG); | |
400 FLOAT_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_FLOAT); | |
401 DOUBLE_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_DOUBLE); | |
402 OBJECT_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_OBJECT); | |
403 | |
404 BOOLEAN_SIZE = objectHeap.getBooleanSize(); | |
405 BYTE_SIZE = objectHeap.getByteSize(); | |
406 CHAR_SIZE = objectHeap.getCharSize(); | |
407 SHORT_SIZE = objectHeap.getShortSize(); | |
408 INT_SIZE = objectHeap.getIntSize(); | |
409 LONG_SIZE = objectHeap.getLongSize(); | |
410 FLOAT_SIZE = objectHeap.getFloatSize(); | |
411 DOUBLE_SIZE = objectHeap.getDoubleSize(); | |
412 | |
12820
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
413 // Check weather we should dump the heap as segments |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
414 useSegmentedHeapDump = vm.getUniverse().heap().used() > HPROF_SEGMENTED_HEAP_DUMP_THRESHOLD; |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
415 |
0 | 416 // hprof bin format header |
417 writeFileHeader(); | |
418 | |
419 // dummy stack trace without any frames so that | |
420 // HAT can be run without -stack false option | |
421 writeDummyTrace(); | |
422 | |
423 // hprof UTF-8 symbols section | |
424 writeSymbols(); | |
12820
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
425 |
0 | 426 // HPROF_LOAD_CLASS records for all classes |
427 writeClasses(); | |
428 | |
429 // write CLASS_DUMP records | |
430 writeClassDumpRecords(); | |
431 | |
432 // this will write heap data into the buffer stream | |
433 super.write(); | |
434 | |
12820
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
435 // flush buffer stream. |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
436 out.flush(); |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
437 |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
438 // Fill in final length |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
439 fillInHeapRecordLength(); |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
440 |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
441 if (useSegmentedHeapDump) { |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
442 // Write heap segment-end record |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
443 out.writeByte((byte) HPROF_HEAP_DUMP_END); |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
444 out.writeInt(0); |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
445 out.writeInt(0); |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
446 } |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
447 |
0 | 448 // flush buffer stream and throw it. |
449 out.flush(); | |
450 out = null; | |
451 | |
12820
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
452 // close the file stream |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
453 fos.close(); |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
454 } |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
455 |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
456 @Override |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
457 protected void writeHeapRecordPrologue() throws IOException { |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
458 if (currentSegmentStart == 0) { |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
459 // write heap data header, depending on heap size use segmented heap |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
460 // format |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
461 out.writeByte((byte) (useSegmentedHeapDump ? HPROF_HEAP_DUMP_SEGMENT |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
462 : HPROF_HEAP_DUMP)); |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
463 out.writeInt(0); |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
464 |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
465 // remember position of dump length, we will fixup |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
466 // length later - hprof format requires length. |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
467 out.flush(); |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
468 currentSegmentStart = fos.getChannel().position(); |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
469 |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
470 // write dummy length of 0 and we'll fix it later. |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
471 out.writeInt(0); |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
472 } |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
473 } |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
474 |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
475 @Override |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
476 protected void writeHeapRecordEpilogue() throws IOException { |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
477 if (useSegmentedHeapDump) { |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
478 out.flush(); |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
479 if ((fos.getChannel().position() - currentSegmentStart - 4) >= HPROF_SEGMENTED_HEAP_DUMP_SEGMENT_SIZE) { |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
480 fillInHeapRecordLength(); |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
481 currentSegmentStart = 0; |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
482 } |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
483 } |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
484 } |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
485 |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
486 private void fillInHeapRecordLength() throws IOException { |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
487 |
0 | 488 // now get current position to calculate length |
12820
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
489 long dumpEnd = fos.getChannel().position(); |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
490 |
0 | 491 // calculate length of heap data |
12820
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
492 long dumpLenLong = (dumpEnd - currentSegmentStart - 4L); |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
493 |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
494 // Check length boundary, overflow could happen but is _very_ unlikely |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
495 if(dumpLenLong >= (4L * 0x40000000)){ |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
496 throw new RuntimeException("Heap segment size overflow."); |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
497 } |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
498 |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
499 // Save the current position |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
500 long currentPosition = fos.getChannel().position(); |
0 | 501 |
502 // seek the position to write length | |
12820
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
503 fos.getChannel().position(currentSegmentStart); |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
504 |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
505 int dumpLen = (int) dumpLenLong; |
0 | 506 |
507 // write length as integer | |
508 fos.write((dumpLen >>> 24) & 0xFF); | |
509 fos.write((dumpLen >>> 16) & 0xFF); | |
510 fos.write((dumpLen >>> 8) & 0xFF); | |
511 fos.write((dumpLen >>> 0) & 0xFF); | |
512 | |
12820
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
513 //Reset to previous current position |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
514 fos.getChannel().position(currentPosition); |
0 | 515 } |
516 | |
517 private void writeClassDumpRecords() throws IOException { | |
518 SystemDictionary sysDict = VM.getVM().getSystemDictionary(); | |
519 try { | |
520 sysDict.allClassesDo(new SystemDictionary.ClassVisitor() { | |
521 public void visit(Klass k) { | |
522 try { | |
12820
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
523 writeHeapRecordPrologue(); |
0 | 524 writeClassDumpRecord(k); |
12820
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
525 writeHeapRecordEpilogue(); |
0 | 526 } catch (IOException e) { |
527 throw new RuntimeException(e); | |
528 } | |
529 } | |
530 }); | |
531 } catch (RuntimeException re) { | |
532 handleRuntimeException(re); | |
533 } | |
534 } | |
535 | |
536 protected void writeClass(Instance instance) throws IOException { | |
2411
63997f575155
7031614: jmap -permstat fails with java.lang.InternalError in sun.jvm.hotspot.oops.OopField.getValue
never
parents:
2380
diff
changeset
|
537 Klass reflectedKlass = java_lang_Class.asKlass(instance); |
0 | 538 // dump instance record only for primitive type Class objects. |
539 // all other Class objects are covered by writeClassDumpRecords. | |
540 if (reflectedKlass == null) { | |
541 writeInstance(instance); | |
542 } | |
543 } | |
544 | |
545 private void writeClassDumpRecord(Klass k) throws IOException { | |
546 out.writeByte((byte)HPROF_GC_CLASS_DUMP); | |
547 writeObjectID(k.getJavaMirror()); | |
548 out.writeInt(DUMMY_STACK_TRACE_ID); | |
549 Klass superKlass = k.getJavaSuper(); | |
550 if (superKlass != null) { | |
551 writeObjectID(superKlass.getJavaMirror()); | |
552 } else { | |
553 writeObjectID(null); | |
554 } | |
555 | |
556 if (k instanceof InstanceKlass) { | |
557 InstanceKlass ik = (InstanceKlass) k; | |
558 writeObjectID(ik.getClassLoader()); | |
10343
6bd680e9ea35
8003421: NPG: Move oops out of InstanceKlass into mirror
coleenp
parents:
6725
diff
changeset
|
559 writeObjectID(null); // ik.getJavaMirror().getSigners()); |
6bd680e9ea35
8003421: NPG: Move oops out of InstanceKlass into mirror
coleenp
parents:
6725
diff
changeset
|
560 writeObjectID(null); // ik.getJavaMirror().getProtectionDomain()); |
0 | 561 // two reserved id fields |
562 writeObjectID(null); | |
563 writeObjectID(null); | |
564 List fields = getInstanceFields(ik); | |
565 int instSize = getSizeForFields(fields); | |
566 classDataCache.put(ik, new ClassData(instSize, fields)); | |
567 out.writeInt(instSize); | |
568 | |
569 // For now, ignore constant pool - HAT ignores too! | |
570 // output number of cp entries as zero. | |
571 out.writeShort((short) 0); | |
572 | |
573 List declaredFields = ik.getImmediateFields(); | |
574 List staticFields = new ArrayList(); | |
575 List instanceFields = new ArrayList(); | |
576 Iterator itr = null; | |
577 for (itr = declaredFields.iterator(); itr.hasNext();) { | |
578 Field field = (Field) itr.next(); | |
579 if (field.isStatic()) { | |
580 staticFields.add(field); | |
581 } else { | |
582 instanceFields.add(field); | |
583 } | |
584 } | |
585 | |
586 // dump static field descriptors | |
587 writeFieldDescriptors(staticFields, ik); | |
588 | |
589 // dump instance field descriptors | |
590 writeFieldDescriptors(instanceFields, null); | |
591 } else { | |
592 if (k instanceof ObjArrayKlass) { | |
593 ObjArrayKlass oak = (ObjArrayKlass) k; | |
594 Klass bottomKlass = oak.getBottomKlass(); | |
595 if (bottomKlass instanceof InstanceKlass) { | |
596 InstanceKlass ik = (InstanceKlass) bottomKlass; | |
597 writeObjectID(ik.getClassLoader()); | |
10343
6bd680e9ea35
8003421: NPG: Move oops out of InstanceKlass into mirror
coleenp
parents:
6725
diff
changeset
|
598 writeObjectID(null); // ik.getJavaMirror().getSigners()); |
6bd680e9ea35
8003421: NPG: Move oops out of InstanceKlass into mirror
coleenp
parents:
6725
diff
changeset
|
599 writeObjectID(null); // ik.getJavaMirror().getProtectionDomain()); |
0 | 600 } else { |
601 writeObjectID(null); | |
602 writeObjectID(null); | |
603 writeObjectID(null); | |
604 } | |
605 } else { | |
606 writeObjectID(null); | |
607 writeObjectID(null); | |
608 writeObjectID(null); | |
609 } | |
610 // two reserved id fields | |
611 writeObjectID(null); | |
612 writeObjectID(null); | |
613 // write zero instance size -- as instance size | |
614 // is variable for arrays. | |
615 out.writeInt(0); | |
616 // no constant pool for array klasses | |
617 out.writeShort((short) 0); | |
618 // no static fields for array klasses | |
619 out.writeShort((short) 0); | |
620 // no instance fields for array klasses | |
621 out.writeShort((short) 0); | |
622 } | |
623 } | |
624 | |
625 protected void writeJavaThread(JavaThread jt, int index) throws IOException { | |
626 out.writeByte((byte) HPROF_GC_ROOT_THREAD_OBJ); | |
627 writeObjectID(jt.getThreadObj()); | |
628 out.writeInt(index); | |
629 out.writeInt(DUMMY_STACK_TRACE_ID); | |
630 writeLocalJNIHandles(jt, index); | |
631 } | |
632 | |
633 protected void writeLocalJNIHandles(JavaThread jt, int index) throws IOException { | |
634 final int threadIndex = index; | |
635 JNIHandleBlock blk = jt.activeHandles(); | |
636 if (blk != null) { | |
637 try { | |
638 blk.oopsDo(new AddressVisitor() { | |
639 public void visitAddress(Address handleAddr) { | |
640 try { | |
641 if (handleAddr != null) { | |
642 OopHandle oopHandle = handleAddr.getOopHandleAt(0); | |
643 Oop oop = objectHeap.newOop(oopHandle); | |
644 // exclude JNI handles hotspot internal objects | |
645 if (oop != null && isJavaVisible(oop)) { | |
646 out.writeByte((byte) HPROF_GC_ROOT_JNI_LOCAL); | |
647 writeObjectID(oop); | |
648 out.writeInt(threadIndex); | |
649 out.writeInt(EMPTY_FRAME_DEPTH); | |
650 } | |
651 } | |
652 } catch (IOException exp) { | |
653 throw new RuntimeException(exp); | |
654 } | |
655 } | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
656 public void visitCompOopAddress(Address handleAddr) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
657 throw new RuntimeException( |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
658 " 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
|
659 } |
0 | 660 }); |
661 } catch (RuntimeException re) { | |
662 handleRuntimeException(re); | |
663 } | |
664 } | |
665 } | |
666 | |
667 protected void writeGlobalJNIHandle(Address handleAddr) throws IOException { | |
668 OopHandle oopHandle = handleAddr.getOopHandleAt(0); | |
669 Oop oop = objectHeap.newOop(oopHandle); | |
670 // exclude JNI handles of hotspot internal objects | |
671 if (oop != null && isJavaVisible(oop)) { | |
672 out.writeByte((byte) HPROF_GC_ROOT_JNI_GLOBAL); | |
673 writeObjectID(oop); | |
674 // use JNIHandle address as ID | |
675 writeObjectID(getAddressValue(handleAddr)); | |
676 } | |
677 } | |
678 | |
679 protected void writeObjectArray(ObjArray array) throws IOException { | |
680 out.writeByte((byte) HPROF_GC_OBJ_ARRAY_DUMP); | |
681 writeObjectID(array); | |
682 out.writeInt(DUMMY_STACK_TRACE_ID); | |
683 out.writeInt((int) array.getLength()); | |
684 writeObjectID(array.getKlass().getJavaMirror()); | |
685 final int length = (int) array.getLength(); | |
686 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
|
687 OopHandle handle = array.getOopHandleAt(index); |
0 | 688 writeObjectID(getAddressValue(handle)); |
689 } | |
690 } | |
691 | |
692 protected void writePrimitiveArray(TypeArray array) throws IOException { | |
693 out.writeByte((byte) HPROF_GC_PRIM_ARRAY_DUMP); | |
694 writeObjectID(array); | |
695 out.writeInt(DUMMY_STACK_TRACE_ID); | |
696 out.writeInt((int) array.getLength()); | |
697 TypeArrayKlass tak = (TypeArrayKlass) array.getKlass(); | |
698 final int type = (int) tak.getElementType(); | |
699 out.writeByte((byte) type); | |
700 switch (type) { | |
701 case TypeArrayKlass.T_BOOLEAN: | |
702 writeBooleanArray(array); | |
703 break; | |
704 case TypeArrayKlass.T_CHAR: | |
705 writeCharArray(array); | |
706 break; | |
707 case TypeArrayKlass.T_FLOAT: | |
708 writeFloatArray(array); | |
709 break; | |
710 case TypeArrayKlass.T_DOUBLE: | |
711 writeDoubleArray(array); | |
712 break; | |
713 case TypeArrayKlass.T_BYTE: | |
714 writeByteArray(array); | |
715 break; | |
716 case TypeArrayKlass.T_SHORT: | |
717 writeShortArray(array); | |
718 break; | |
719 case TypeArrayKlass.T_INT: | |
720 writeIntArray(array); | |
721 break; | |
722 case TypeArrayKlass.T_LONG: | |
723 writeLongArray(array); | |
724 break; | |
725 default: | |
726 throw new RuntimeException("should not reach here"); | |
727 } | |
728 } | |
729 | |
730 private void writeBooleanArray(TypeArray array) throws IOException { | |
731 final int length = (int) array.getLength(); | |
732 for (int index = 0; index < length; index++) { | |
733 long offset = BOOLEAN_BASE_OFFSET + index * BOOLEAN_SIZE; | |
734 out.writeBoolean(array.getHandle().getJBooleanAt(offset)); | |
735 } | |
736 } | |
737 | |
738 private void writeByteArray(TypeArray array) throws IOException { | |
739 final int length = (int) array.getLength(); | |
740 for (int index = 0; index < length; index++) { | |
741 long offset = BYTE_BASE_OFFSET + index * BYTE_SIZE; | |
742 out.writeByte(array.getHandle().getJByteAt(offset)); | |
743 } | |
744 } | |
745 | |
746 private void writeShortArray(TypeArray array) throws IOException { | |
747 final int length = (int) array.getLength(); | |
748 for (int index = 0; index < length; index++) { | |
749 long offset = SHORT_BASE_OFFSET + index * SHORT_SIZE; | |
750 out.writeShort(array.getHandle().getJShortAt(offset)); | |
751 } | |
752 } | |
753 | |
754 private void writeIntArray(TypeArray array) throws IOException { | |
755 final int length = (int) array.getLength(); | |
756 for (int index = 0; index < length; index++) { | |
757 long offset = INT_BASE_OFFSET + index * INT_SIZE; | |
758 out.writeInt(array.getHandle().getJIntAt(offset)); | |
759 } | |
760 } | |
761 | |
762 private void writeLongArray(TypeArray array) throws IOException { | |
763 final int length = (int) array.getLength(); | |
764 for (int index = 0; index < length; index++) { | |
765 long offset = LONG_BASE_OFFSET + index * LONG_SIZE; | |
766 out.writeLong(array.getHandle().getJLongAt(offset)); | |
767 } | |
768 } | |
769 | |
770 private void writeCharArray(TypeArray array) throws IOException { | |
771 final int length = (int) array.getLength(); | |
772 for (int index = 0; index < length; index++) { | |
773 long offset = CHAR_BASE_OFFSET + index * CHAR_SIZE; | |
774 out.writeChar(array.getHandle().getJCharAt(offset)); | |
775 } | |
776 } | |
777 | |
778 private void writeFloatArray(TypeArray array) throws IOException { | |
779 final int length = (int) array.getLength(); | |
780 for (int index = 0; index < length; index++) { | |
781 long offset = FLOAT_BASE_OFFSET + index * FLOAT_SIZE; | |
782 out.writeFloat(array.getHandle().getJFloatAt(offset)); | |
783 } | |
784 } | |
785 | |
786 private void writeDoubleArray(TypeArray array) throws IOException { | |
787 final int length = (int) array.getLength(); | |
788 for (int index = 0; index < length; index++) { | |
789 long offset = DOUBLE_BASE_OFFSET + index * DOUBLE_SIZE; | |
790 out.writeDouble(array.getHandle().getJDoubleAt(offset)); | |
791 } | |
792 } | |
793 | |
794 protected void writeInstance(Instance instance) throws IOException { | |
795 out.writeByte((byte) HPROF_GC_INSTANCE_DUMP); | |
796 writeObjectID(instance); | |
797 out.writeInt(DUMMY_STACK_TRACE_ID); | |
798 Klass klass = instance.getKlass(); | |
799 writeObjectID(klass.getJavaMirror()); | |
800 | |
801 ClassData cd = (ClassData) classDataCache.get(klass); | |
802 if (Assert.ASSERTS_ENABLED) { | |
6725
da91efe96a93
6964458: Reimplement class meta-data storage to use native memory
coleenp
parents:
2411
diff
changeset
|
803 Assert.that(cd != null, "can not get class data for " + klass.getName().asString() + klass.getAddress()); |
0 | 804 } |
805 List fields = cd.fields; | |
806 int size = cd.instSize; | |
807 out.writeInt(size); | |
808 for (Iterator itr = fields.iterator(); itr.hasNext();) { | |
809 writeField((Field) itr.next(), instance); | |
810 } | |
811 } | |
812 | |
813 //-- Internals only below this point | |
814 | |
815 private void writeFieldDescriptors(List fields, InstanceKlass ik) | |
816 throws IOException { | |
817 // ik == null for instance fields. | |
818 out.writeShort((short) fields.size()); | |
819 for (Iterator itr = fields.iterator(); itr.hasNext();) { | |
820 Field field = (Field) itr.next(); | |
821 Symbol name = symTbl.probe(field.getID().getName()); | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1552
diff
changeset
|
822 writeSymbolID(name); |
0 | 823 char typeCode = (char) field.getSignature().getByteAt(0); |
824 int kind = signatureToHprofKind(typeCode); | |
825 out.writeByte((byte)kind); | |
826 if (ik != null) { | |
827 // static field | |
2380
32f7097f9d8f
7030300: more nightly failures after statics in Class changes
never
parents:
2177
diff
changeset
|
828 writeField(field, ik.getJavaMirror()); |
0 | 829 } |
830 } | |
831 } | |
832 | |
833 public static int signatureToHprofKind(char ch) { | |
834 switch (ch) { | |
835 case JVM_SIGNATURE_CLASS: | |
836 case JVM_SIGNATURE_ARRAY: | |
837 return HPROF_NORMAL_OBJECT; | |
838 case JVM_SIGNATURE_BOOLEAN: | |
839 return HPROF_BOOLEAN; | |
840 case JVM_SIGNATURE_CHAR: | |
841 return HPROF_CHAR; | |
842 case JVM_SIGNATURE_FLOAT: | |
843 return HPROF_FLOAT; | |
844 case JVM_SIGNATURE_DOUBLE: | |
845 return HPROF_DOUBLE; | |
846 case JVM_SIGNATURE_BYTE: | |
847 return HPROF_BYTE; | |
848 case JVM_SIGNATURE_SHORT: | |
849 return HPROF_SHORT; | |
850 case JVM_SIGNATURE_INT: | |
851 return HPROF_INT; | |
852 case JVM_SIGNATURE_LONG: | |
853 return HPROF_LONG; | |
854 default: | |
855 throw new RuntimeException("should not reach here"); | |
856 } | |
857 } | |
858 | |
859 private void writeField(Field field, Oop oop) throws IOException { | |
860 char typeCode = (char) field.getSignature().getByteAt(0); | |
861 switch (typeCode) { | |
862 case JVM_SIGNATURE_BOOLEAN: | |
863 out.writeBoolean(((BooleanField)field).getValue(oop)); | |
864 break; | |
865 case JVM_SIGNATURE_CHAR: | |
866 out.writeChar(((CharField)field).getValue(oop)); | |
867 break; | |
868 case JVM_SIGNATURE_BYTE: | |
869 out.writeByte(((ByteField)field).getValue(oop)); | |
870 break; | |
871 case JVM_SIGNATURE_SHORT: | |
872 out.writeShort(((ShortField)field).getValue(oop)); | |
873 break; | |
874 case JVM_SIGNATURE_INT: | |
875 out.writeInt(((IntField)field).getValue(oop)); | |
876 break; | |
877 case JVM_SIGNATURE_LONG: | |
878 out.writeLong(((LongField)field).getValue(oop)); | |
879 break; | |
880 case JVM_SIGNATURE_FLOAT: | |
881 out.writeFloat(((FloatField)field).getValue(oop)); | |
882 break; | |
883 case JVM_SIGNATURE_DOUBLE: | |
884 out.writeDouble(((DoubleField)field).getValue(oop)); | |
885 break; | |
886 case JVM_SIGNATURE_CLASS: | |
887 case JVM_SIGNATURE_ARRAY: { | |
113
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
888 if (VM.getVM().isCompressedOopsEnabled()) { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
889 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
|
890 writeObjectID(getAddressValue(handle)); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
891 } else { |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
892 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
|
893 writeObjectID(getAddressValue(handle)); |
ba764ed4b6f2
6420645: Create a vm that uses compressed oops for up to 32gb heapsizes
coleenp
parents:
0
diff
changeset
|
894 } |
0 | 895 break; |
896 } | |
897 default: | |
898 throw new RuntimeException("should not reach here"); | |
899 } | |
900 } | |
901 | |
902 private void writeHeader(int tag, int len) throws IOException { | |
903 out.writeByte((byte)tag); | |
904 out.writeInt(0); // current ticks | |
905 out.writeInt(len); | |
906 } | |
907 | |
908 private void writeDummyTrace() throws IOException { | |
909 writeHeader(HPROF_TRACE, 3 * 4); | |
910 out.writeInt(DUMMY_STACK_TRACE_ID); | |
911 out.writeInt(0); | |
912 out.writeInt(0); | |
913 } | |
914 | |
915 private void writeSymbols() throws IOException { | |
916 try { | |
917 symTbl.symbolsDo(new SymbolTable.SymbolVisitor() { | |
918 public void visit(Symbol sym) { | |
919 try { | |
920 writeSymbol(sym); | |
921 } catch (IOException exp) { | |
922 throw new RuntimeException(exp); | |
923 } | |
924 } | |
925 }); | |
926 } catch (RuntimeException re) { | |
927 handleRuntimeException(re); | |
928 } | |
929 } | |
930 | |
931 private void writeSymbol(Symbol sym) throws IOException { | |
932 byte[] buf = sym.asString().getBytes("UTF-8"); | |
933 writeHeader(HPROF_UTF8, buf.length + OBJ_ID_SIZE); | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1552
diff
changeset
|
934 writeSymbolID(sym); |
0 | 935 out.write(buf); |
936 } | |
937 | |
938 private void writeClasses() throws IOException { | |
939 // write class list (id, name) association | |
940 SystemDictionary sysDict = VM.getVM().getSystemDictionary(); | |
941 try { | |
942 sysDict.allClassesDo(new SystemDictionary.ClassVisitor() { | |
943 private int serialNum = 1; | |
944 public void visit(Klass k) { | |
945 try { | |
946 Instance clazz = k.getJavaMirror(); | |
947 writeHeader(HPROF_LOAD_CLASS, 2 * (OBJ_ID_SIZE + 4)); | |
948 out.writeInt(serialNum); | |
949 writeObjectID(clazz); | |
950 out.writeInt(DUMMY_STACK_TRACE_ID); | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1552
diff
changeset
|
951 writeSymbolID(k.getName()); |
0 | 952 serialNum++; |
953 } catch (IOException exp) { | |
954 throw new RuntimeException(exp); | |
955 } | |
956 } | |
957 }); | |
958 } catch (RuntimeException re) { | |
959 handleRuntimeException(re); | |
960 } | |
961 } | |
962 | |
963 // writes hprof binary file header | |
964 private void writeFileHeader() throws IOException { | |
965 // version string | |
12820
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
966 if(useSegmentedHeapDump) { |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
967 out.writeBytes(HPROF_HEADER_1_0_2); |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
968 } |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
969 else { |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
970 out.writeBytes(HPROF_HEADER_1_0_1); |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
971 } |
0 | 972 out.writeByte((byte)'\0'); |
973 | |
974 // write identifier size. we use pointers as identifiers. | |
975 out.writeInt(OBJ_ID_SIZE); | |
976 | |
977 // timestamp -- file creation time. | |
978 out.writeLong(System.currentTimeMillis()); | |
979 } | |
980 | |
981 // writes unique ID for an object | |
982 private void writeObjectID(Oop oop) throws IOException { | |
983 OopHandle handle = (oop != null)? oop.getHandle() : null; | |
984 long address = getAddressValue(handle); | |
985 writeObjectID(address); | |
986 } | |
987 | |
2177
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1552
diff
changeset
|
988 private void writeSymbolID(Symbol sym) throws IOException { |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1552
diff
changeset
|
989 writeObjectID(getAddressValue(sym.getAddress())); |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1552
diff
changeset
|
990 } |
3582bf76420e
6990754: Use native memory and reference counting to implement SymbolTable
coleenp
parents:
1552
diff
changeset
|
991 |
0 | 992 private void writeObjectID(long address) throws IOException { |
993 if (OBJ_ID_SIZE == 4) { | |
994 out.writeInt((int) address); | |
995 } else { | |
996 out.writeLong(address); | |
997 } | |
998 } | |
999 | |
1000 private long getAddressValue(Address addr) { | |
1001 return (addr == null)? 0L : dbg.getAddressValue(addr); | |
1002 } | |
1003 | |
1004 // get all declared as well as inherited (directly/indirectly) fields | |
1005 private static List/*<Field>*/ getInstanceFields(InstanceKlass ik) { | |
1006 InstanceKlass klass = ik; | |
1007 List res = new ArrayList(); | |
1008 while (klass != null) { | |
1009 List curFields = klass.getImmediateFields(); | |
1010 for (Iterator itr = curFields.iterator(); itr.hasNext();) { | |
1011 Field f = (Field) itr.next(); | |
1012 if (! f.isStatic()) { | |
1013 res.add(f); | |
1014 } | |
1015 } | |
1016 klass = (InstanceKlass) klass.getSuper(); | |
1017 } | |
1018 return res; | |
1019 } | |
1020 | |
1021 // get size in bytes (in stream) required for given fields. Note | |
1022 // that this is not the same as object size in heap. The size in | |
1023 // heap will include size of padding/alignment bytes as well. | |
1024 private int getSizeForFields(List fields) { | |
1025 int size = 0; | |
1026 for (Iterator itr = fields.iterator(); itr.hasNext();) { | |
1027 Field field = (Field) itr.next(); | |
1028 char typeCode = (char) field.getSignature().getByteAt(0); | |
1029 switch (typeCode) { | |
1030 case JVM_SIGNATURE_BOOLEAN: | |
1031 case JVM_SIGNATURE_BYTE: | |
1032 size++; | |
1033 break; | |
1034 case JVM_SIGNATURE_CHAR: | |
1035 case JVM_SIGNATURE_SHORT: | |
1036 size += 2; | |
1037 break; | |
1038 case JVM_SIGNATURE_INT: | |
1039 case JVM_SIGNATURE_FLOAT: | |
1040 size += 4; | |
1041 break; | |
1042 case JVM_SIGNATURE_CLASS: | |
1043 case JVM_SIGNATURE_ARRAY: | |
1044 size += OBJ_ID_SIZE; | |
1045 break; | |
1046 case JVM_SIGNATURE_LONG: | |
1047 case JVM_SIGNATURE_DOUBLE: | |
1048 size += 8; | |
1049 break; | |
1050 default: | |
1051 throw new RuntimeException("should not reach here"); | |
1052 } | |
1053 } | |
1054 return size; | |
1055 } | |
1056 | |
1057 // We don't have allocation site info. We write a dummy | |
1058 // stack trace with this id. | |
1059 private static final int DUMMY_STACK_TRACE_ID = 1; | |
1060 private static final int EMPTY_FRAME_DEPTH = -1; | |
1061 | |
1062 private DataOutputStream out; | |
12820
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
1063 private FileOutputStream fos; |
0 | 1064 private Debugger dbg; |
1065 private ObjectHeap objectHeap; | |
1066 private SymbolTable symTbl; | |
1067 | |
1068 // oopSize of the debuggee | |
1069 private int OBJ_ID_SIZE; | |
1070 | |
12820
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
1071 // Added for hprof file format 1.0.2 support |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
1072 private boolean useSegmentedHeapDump; |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
1073 private long currentSegmentStart; |
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
1074 |
0 | 1075 private long BOOLEAN_BASE_OFFSET; |
1076 private long BYTE_BASE_OFFSET; | |
1077 private long CHAR_BASE_OFFSET; | |
1078 private long SHORT_BASE_OFFSET; | |
1079 private long INT_BASE_OFFSET; | |
1080 private long LONG_BASE_OFFSET; | |
1081 private long FLOAT_BASE_OFFSET; | |
1082 private long DOUBLE_BASE_OFFSET; | |
1083 private long OBJECT_BASE_OFFSET; | |
1084 | |
1085 private long BOOLEAN_SIZE; | |
1086 private long BYTE_SIZE; | |
1087 private long CHAR_SIZE; | |
1088 private long SHORT_SIZE; | |
1089 private long INT_SIZE; | |
1090 private long LONG_SIZE; | |
1091 private long FLOAT_SIZE; | |
1092 private long DOUBLE_SIZE; | |
1093 | |
1094 private static class ClassData { | |
1095 int instSize; | |
1096 List fields; | |
12820
8ef918538e22
6313383: SA: Update jmap to support HPROF binary format "JAVA PROFILE 1.0.2"
sla
parents:
10343
diff
changeset
|
1097 |
0 | 1098 ClassData(int instSize, List fields) { |
1099 this.instSize = instSize; | |
1100 this.fields = fields; | |
1101 } | |
1102 } | |
1103 | |
1104 private Map classDataCache = new HashMap(); // <InstanceKlass, ClassData> | |
1105 } |