1 /* 2 * Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * 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 import sun.jvm.hotspot.classfile.*; 35 import sun.jvm.hotspot.gc.z.ZCollectedHeap; 36 37 /* 38 * This class writes Java heap in hprof binary format. This format is 39 * used by Heap Analysis Tool (HAT). The class is heavily influenced 40 * by 'hprof_io.c' of 1.5 new hprof implementation. 41 */ 42 43 /* hprof binary format: (result either written to a file or sent over 44 * the network). 45 * 46 * WARNING: This format is still under development, and is subject to 47 * change without notice. 48 * 49 * header "JAVA PROFILE 1.0.2" (0-terminated) 50 * u4 size of identifiers. Identifiers are used to represent 51 * UTF8 strings, objects, stack traces, etc. They usually 52 * have the same size as host pointers. For example, on 53 * Solaris and Win32, the size is 4. 54 * u4 high word 55 * u4 low word number of milliseconds since 0:00 GMT, 1/1/70 56 * [record]* a sequence of records. 57 * 58 */ 59 60 /* 61 * 62 * Record format: 63 * 64 * u1 a TAG denoting the type of the record 65 * u4 number of *microseconds* since the time stamp in the 66 * header. (wraps around in a little more than an hour) 67 * u4 number of bytes *remaining* in the record. Note that 68 * this number excludes the tag and the length field itself. 69 * [u1]* BODY of the record (a sequence of bytes) 70 */ 71 72 /* 73 * The following TAGs are supported: 74 * 75 * TAG BODY notes 76 *---------------------------------------------------------- 77 * HPROF_UTF8 a UTF8-encoded name 78 * 79 * id name ID 80 * [u1]* UTF8 characters (no trailing zero) 81 * 82 * HPROF_LOAD_CLASS a newly loaded class 83 * 84 * u4 class serial number (> 0) 85 * id class object ID 86 * u4 stack trace serial number 87 * id class name ID 88 * 89 * HPROF_UNLOAD_CLASS an unloading class 90 * 91 * u4 class serial_number 92 * 93 * HPROF_FRAME a Java stack frame 94 * 95 * id stack frame ID 96 * id method name ID 97 * id method signature ID 98 * id source file name ID 99 * u4 class serial number 100 * i4 line number. >0: normal 101 * -1: unknown 102 * -2: compiled method 103 * -3: native method 104 * 105 * HPROF_TRACE a Java stack trace 106 * 107 * u4 stack trace serial number 108 * u4 thread serial number 109 * u4 number of frames 110 * [id]* stack frame IDs 111 * 112 * 113 * HPROF_ALLOC_SITES a set of heap allocation sites, obtained after GC 114 * 115 * u2 flags 0x0001: incremental vs. complete 116 * 0x0002: sorted by allocation vs. live 117 * 0x0004: whether to force a GC 118 * u4 cutoff ratio 119 * u4 total live bytes 120 * u4 total live instances 121 * u8 total bytes allocated 122 * u8 total instances allocated 123 * u4 number of sites that follow 124 * [u1 is_array: 0: normal object 125 * 2: object array 126 * 4: boolean array 127 * 5: char array 128 * 6: float array 129 * 7: double array 130 * 8: byte array 131 * 9: short array 132 * 10: int array 133 * 11: long array 134 * u4 class serial number (may be zero during startup) 135 * u4 stack trace serial number 136 * u4 number of bytes alive 137 * u4 number of instances alive 138 * u4 number of bytes allocated 139 * u4]* number of instance allocated 140 * 141 * HPROF_START_THREAD a newly started thread. 142 * 143 * u4 thread serial number (> 0) 144 * id thread object ID 145 * u4 stack trace serial number 146 * id thread name ID 147 * id thread group name ID 148 * id thread group parent name ID 149 * 150 * HPROF_END_THREAD a terminating thread. 151 * 152 * u4 thread serial number 153 * 154 * HPROF_HEAP_SUMMARY heap summary 155 * 156 * u4 total live bytes 157 * u4 total live instances 158 * u8 total bytes allocated 159 * u8 total instances allocated 160 * 161 * HPROF_HEAP_DUMP denote a heap dump 162 * 163 * [heap dump sub-records]* 164 * 165 * There are four kinds of heap dump sub-records: 166 * 167 * u1 sub-record type 168 * 169 * HPROF_GC_ROOT_UNKNOWN unknown root 170 * 171 * id object ID 172 * 173 * HPROF_GC_ROOT_THREAD_OBJ thread object 174 * 175 * id thread object ID (may be 0 for a 176 * thread newly attached through JNI) 177 * u4 thread sequence number 178 * u4 stack trace sequence number 179 * 180 * HPROF_GC_ROOT_JNI_GLOBAL JNI global ref root 181 * 182 * id object ID 183 * id JNI global ref ID 184 * 185 * HPROF_GC_ROOT_JNI_LOCAL JNI local ref 186 * 187 * id object ID 188 * u4 thread serial number 189 * u4 frame # in stack trace (-1 for empty) 190 * 191 * HPROF_GC_ROOT_JAVA_FRAME Java stack frame 192 * 193 * id object ID 194 * u4 thread serial number 195 * u4 frame # in stack trace (-1 for empty) 196 * 197 * HPROF_GC_ROOT_NATIVE_STACK Native stack 198 * 199 * id object ID 200 * u4 thread serial number 201 * 202 * HPROF_GC_ROOT_STICKY_CLASS System class 203 * 204 * id object ID 205 * 206 * HPROF_GC_ROOT_THREAD_BLOCK Reference from thread block 207 * 208 * id object ID 209 * u4 thread serial number 210 * 211 * HPROF_GC_ROOT_MONITOR_USED Busy monitor 212 * 213 * id object ID 214 * 215 * HPROF_GC_CLASS_DUMP dump of a class object 216 * 217 * id class object ID 218 * u4 stack trace serial number 219 * id super class object ID 220 * id class loader object ID 221 * id signers object ID 222 * id protection domain object ID 223 * id reserved 224 * id reserved 225 * 226 * u4 instance size (in bytes) 227 * 228 * u2 size of constant pool 229 * [u2, constant pool index, 230 * ty, type 231 * 2: object 232 * 4: boolean 233 * 5: char 234 * 6: float 235 * 7: double 236 * 8: byte 237 * 9: short 238 * 10: int 239 * 11: long 240 * vl]* and value 241 * 242 * u2 number of static fields 243 * [id, static field name, 244 * ty, type, 245 * vl]* and value 246 * 247 * u2 number of inst. fields (not inc. super) 248 * [id, instance field name, 249 * ty]* type 250 * 251 * HPROF_GC_INSTANCE_DUMP dump of a normal object 252 * 253 * id object ID 254 * u4 stack trace serial number 255 * id class object ID 256 * u4 number of bytes that follow 257 * [vl]* instance field values (class, followed 258 * by super, super's super ...) 259 * 260 * HPROF_GC_OBJ_ARRAY_DUMP dump of an object array 261 * 262 * id array object ID 263 * u4 stack trace serial number 264 * u4 number of elements 265 * id array class ID 266 * [id]* elements 267 * 268 * HPROF_GC_PRIM_ARRAY_DUMP dump of a primitive array 269 * 270 * id array object ID 271 * u4 stack trace serial number 272 * u4 number of elements 273 * u1 element type 274 * 4: boolean array 275 * 5: char array 276 * 6: float array 277 * 7: double array 278 * 8: byte array 279 * 9: short array 280 * 10: int array 281 * 11: long array 282 * [u1]* elements 283 * 284 * HPROF_CPU_SAMPLES a set of sample traces of running threads 285 * 286 * u4 total number of samples 287 * u4 # of traces 288 * [u4 # of samples 289 * u4]* stack trace serial number 290 * 291 * HPROF_CONTROL_SETTINGS the settings of on/off switches 292 * 293 * u4 0x00000001: alloc traces on/off 294 * 0x00000002: cpu sampling on/off 295 * u2 stack trace depth 296 * 297 * 298 * A heap dump can optionally be generated as a sequence of heap dump 299 * segments. This sequence is terminated by an end record. The additional 300 * tags allowed by format "JAVA PROFILE 1.0.2" are: 301 * 302 * HPROF_HEAP_DUMP_SEGMENT denote a heap dump segment 303 * 304 * [heap dump sub-records]* 305 * The same sub-record types allowed by HPROF_HEAP_DUMP 306 * 307 * HPROF_HEAP_DUMP_END denotes the end of a heap dump 308 * 309 */ 310 311 public class HeapHprofBinWriter extends AbstractHeapGraphWriter { 312 313 // Record which Symbol names have been dumped already. 314 private HashSet<Symbol> names; 315 316 private static final long HPROF_SEGMENTED_HEAP_DUMP_THRESHOLD = 2L * 0x40000000; 317 318 // The approximate size of a heap segment. Used to calculate when to create 319 // a new segment. 320 private static final long HPROF_SEGMENTED_HEAP_DUMP_SEGMENT_SIZE = 1L * 0x40000000; 321 322 // hprof binary file header 323 private static final String HPROF_HEADER_1_0_2 = "JAVA PROFILE 1.0.2"; 324 325 // constants in enum HprofTag 326 private static final int HPROF_UTF8 = 0x01; 327 private static final int HPROF_LOAD_CLASS = 0x02; 328 private static final int HPROF_UNLOAD_CLASS = 0x03; 329 private static final int HPROF_FRAME = 0x04; 330 private static final int HPROF_TRACE = 0x05; 331 private static final int HPROF_ALLOC_SITES = 0x06; 332 private static final int HPROF_HEAP_SUMMARY = 0x07; 333 private static final int HPROF_START_THREAD = 0x0A; 334 private static final int HPROF_END_THREAD = 0x0B; 335 private static final int HPROF_HEAP_DUMP = 0x0C; 336 private static final int HPROF_CPU_SAMPLES = 0x0D; 337 private static final int HPROF_CONTROL_SETTINGS = 0x0E; 338 339 // 1.0.2 record types 340 private static final int HPROF_HEAP_DUMP_SEGMENT = 0x1C; 341 private static final int HPROF_HEAP_DUMP_END = 0x2C; 342 343 // Heap dump constants 344 // constants in enum HprofGcTag 345 private static final int HPROF_GC_ROOT_UNKNOWN = 0xFF; 346 private static final int HPROF_GC_ROOT_JNI_GLOBAL = 0x01; 347 private static final int HPROF_GC_ROOT_JNI_LOCAL = 0x02; 348 private static final int HPROF_GC_ROOT_JAVA_FRAME = 0x03; 349 private static final int HPROF_GC_ROOT_NATIVE_STACK = 0x04; 350 private static final int HPROF_GC_ROOT_STICKY_CLASS = 0x05; 351 private static final int HPROF_GC_ROOT_THREAD_BLOCK = 0x06; 352 private static final int HPROF_GC_ROOT_MONITOR_USED = 0x07; 353 private static final int HPROF_GC_ROOT_THREAD_OBJ = 0x08; 354 private static final int HPROF_GC_CLASS_DUMP = 0x20; 355 private static final int HPROF_GC_INSTANCE_DUMP = 0x21; 356 private static final int HPROF_GC_OBJ_ARRAY_DUMP = 0x22; 357 private static final int HPROF_GC_PRIM_ARRAY_DUMP = 0x23; 358 359 // constants in enum HprofType 360 private static final int HPROF_ARRAY_OBJECT = 1; 361 private static final int HPROF_NORMAL_OBJECT = 2; 362 private static final int HPROF_BOOLEAN = 4; 363 private static final int HPROF_CHAR = 5; 364 private static final int HPROF_FLOAT = 6; 365 private static final int HPROF_DOUBLE = 7; 366 private static final int HPROF_BYTE = 8; 367 private static final int HPROF_SHORT = 9; 368 private static final int HPROF_INT = 10; 369 private static final int HPROF_LONG = 11; 370 371 // Java type codes 372 private static final int JVM_SIGNATURE_BOOLEAN = 'Z'; 373 private static final int JVM_SIGNATURE_CHAR = 'C'; 374 private static final int JVM_SIGNATURE_BYTE = 'B'; 375 private static final int JVM_SIGNATURE_SHORT = 'S'; 376 private static final int JVM_SIGNATURE_INT = 'I'; 377 private static final int JVM_SIGNATURE_LONG = 'J'; 378 private static final int JVM_SIGNATURE_FLOAT = 'F'; 379 private static final int JVM_SIGNATURE_DOUBLE = 'D'; 380 private static final int JVM_SIGNATURE_ARRAY = '['; 381 private static final int JVM_SIGNATURE_CLASS = 'L'; 382 383 private static final long MAX_U4_VALUE = 0xFFFFFFFFL; 384 int serialNum = 1; 385 HeapHprofBinWriter()386 public HeapHprofBinWriter() { 387 this.KlassMap = new ArrayList<Klass>(); 388 this.names = new HashSet<Symbol>(); 389 } 390 write(String fileName)391 public synchronized void write(String fileName) throws IOException { 392 VM vm = VM.getVM(); 393 394 // open file stream and create buffered data output stream 395 fos = new FileOutputStream(fileName); 396 out = new DataOutputStream(new BufferedOutputStream(fos)); 397 398 dbg = vm.getDebugger(); 399 objectHeap = vm.getObjectHeap(); 400 401 OBJ_ID_SIZE = (int) vm.getOopSize(); 402 403 BOOLEAN_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_BOOLEAN); 404 BYTE_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_BYTE); 405 CHAR_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_CHAR); 406 SHORT_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_SHORT); 407 INT_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_INT); 408 LONG_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_LONG); 409 FLOAT_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_FLOAT); 410 DOUBLE_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_DOUBLE); 411 OBJECT_BASE_OFFSET = TypeArray.baseOffsetInBytes(BasicType.T_OBJECT); 412 413 BOOLEAN_SIZE = objectHeap.getBooleanSize(); 414 BYTE_SIZE = objectHeap.getByteSize(); 415 CHAR_SIZE = objectHeap.getCharSize(); 416 SHORT_SIZE = objectHeap.getShortSize(); 417 INT_SIZE = objectHeap.getIntSize(); 418 LONG_SIZE = objectHeap.getLongSize(); 419 FLOAT_SIZE = objectHeap.getFloatSize(); 420 DOUBLE_SIZE = objectHeap.getDoubleSize(); 421 422 // Check weather we should dump the heap as segments 423 useSegmentedHeapDump = vm.getUniverse().heap().used() > HPROF_SEGMENTED_HEAP_DUMP_THRESHOLD; 424 425 // hprof bin format header 426 writeFileHeader(); 427 428 // dummy stack trace without any frames so that 429 // HAT can be run without -stack false option 430 writeDummyTrace(); 431 432 // hprof UTF-8 symbols section 433 writeSymbols(); 434 435 // HPROF_LOAD_CLASS records for all classes 436 writeClasses(); 437 438 // write HPROF_FRAME and HPROF_TRACE records 439 dumpStackTraces(); 440 441 // write CLASS_DUMP records 442 writeClassDumpRecords(); 443 444 // this will write heap data into the buffer stream 445 super.write(); 446 447 // flush buffer stream. 448 out.flush(); 449 450 // Fill in final length 451 fillInHeapRecordLength(); 452 453 if (useSegmentedHeapDump) { 454 // Write heap segment-end record 455 out.writeByte((byte) HPROF_HEAP_DUMP_END); 456 out.writeInt(0); 457 out.writeInt(0); 458 } 459 460 // flush buffer stream and throw it. 461 out.flush(); 462 out = null; 463 464 // close the file stream 465 fos.close(); 466 } 467 468 @Override writeHeapRecordPrologue()469 protected void writeHeapRecordPrologue() throws IOException { 470 if (currentSegmentStart == 0) { 471 // write heap data header, depending on heap size use segmented heap 472 // format 473 out.writeByte((byte) (useSegmentedHeapDump ? HPROF_HEAP_DUMP_SEGMENT 474 : HPROF_HEAP_DUMP)); 475 out.writeInt(0); 476 477 // remember position of dump length, we will fixup 478 // length later - hprof format requires length. 479 out.flush(); 480 currentSegmentStart = fos.getChannel().position(); 481 // write dummy length of 0 and we'll fix it later. 482 out.writeInt(0); 483 } 484 } 485 486 @Override writeHeapRecordEpilogue()487 protected void writeHeapRecordEpilogue() throws IOException { 488 if (useSegmentedHeapDump) { 489 out.flush(); 490 if ((fos.getChannel().position() - currentSegmentStart - 4L) >= HPROF_SEGMENTED_HEAP_DUMP_SEGMENT_SIZE) { 491 fillInHeapRecordLength(); 492 currentSegmentStart = 0; 493 } 494 } 495 } 496 fillInHeapRecordLength()497 private void fillInHeapRecordLength() throws IOException { 498 499 // now get the current position to calculate length 500 long dumpEnd = fos.getChannel().position(); 501 502 // calculate the length of heap data 503 long dumpLenLong = (dumpEnd - currentSegmentStart - 4L); 504 505 // Check length boundary, overflow could happen but is _very_ unlikely 506 if (dumpLenLong >= (4L * 0x40000000)) { 507 throw new RuntimeException("Heap segment size overflow."); 508 } 509 510 // Save the current position 511 long currentPosition = fos.getChannel().position(); 512 513 // seek the position to write length 514 fos.getChannel().position(currentSegmentStart); 515 516 int dumpLen = (int) dumpLenLong; 517 518 // write length as integer 519 fos.write((dumpLen >>> 24) & 0xFF); 520 fos.write((dumpLen >>> 16) & 0xFF); 521 fos.write((dumpLen >>> 8) & 0xFF); 522 fos.write((dumpLen >>> 0) & 0xFF); 523 524 //Reset to previous current position 525 fos.getChannel().position(currentPosition); 526 } 527 528 // get the size in bytes for the requested type getSizeForType(int type)529 private long getSizeForType(int type) throws IOException { 530 switch (type) { 531 case TypeArrayKlass.T_BOOLEAN: 532 return BOOLEAN_SIZE; 533 case TypeArrayKlass.T_INT: 534 return INT_SIZE; 535 case TypeArrayKlass.T_CHAR: 536 return CHAR_SIZE; 537 case TypeArrayKlass.T_SHORT: 538 return SHORT_SIZE; 539 case TypeArrayKlass.T_BYTE: 540 return BYTE_SIZE; 541 case TypeArrayKlass.T_LONG: 542 return LONG_SIZE; 543 case TypeArrayKlass.T_FLOAT: 544 return FLOAT_SIZE; 545 case TypeArrayKlass.T_DOUBLE: 546 return DOUBLE_SIZE; 547 default: 548 throw new RuntimeException( 549 "Should not reach here: Unknown type: " + type); 550 } 551 } 552 getArrayHeaderSize(boolean isObjectAarray)553 private int getArrayHeaderSize(boolean isObjectAarray) { 554 return isObjectAarray? 555 ((int) BYTE_SIZE + 2 * (int) INT_SIZE + 2 * (int) OBJ_ID_SIZE): 556 (2 * (int) BYTE_SIZE + 2 * (int) INT_SIZE + (int) OBJ_ID_SIZE); 557 } 558 559 // Check if we need to truncate an array calculateArrayMaxLength(long originalArrayLength, int headerSize, long typeSize, String typeName)560 private int calculateArrayMaxLength(long originalArrayLength, 561 int headerSize, 562 long typeSize, 563 String typeName) throws IOException { 564 565 long length = originalArrayLength; 566 567 // now get the current position to calculate length 568 long dumpEnd = fos.getChannel().position(); 569 long originalLengthInBytes = originalArrayLength * typeSize; 570 571 // calculate the length of heap data 572 long currentRecordLength = (dumpEnd - currentSegmentStart - 4L); 573 if (currentRecordLength > 0 && 574 (currentRecordLength + headerSize + originalLengthInBytes) > MAX_U4_VALUE) { 575 fillInHeapRecordLength(); 576 currentSegmentStart = 0; 577 writeHeapRecordPrologue(); 578 currentRecordLength = 0; 579 } 580 581 // Calculate the max bytes we can use. 582 long maxBytes = (MAX_U4_VALUE - (headerSize + currentRecordLength)); 583 584 if (originalLengthInBytes > maxBytes) { 585 length = maxBytes/typeSize; 586 System.err.println("WARNING: Cannot dump array of type " + typeName 587 + " with length " + originalArrayLength 588 + "; truncating to length " + length); 589 } 590 return (int) length; 591 } 592 writeClassDumpRecords()593 private void writeClassDumpRecords() throws IOException { 594 ClassLoaderDataGraph cldGraph = VM.getVM().getClassLoaderDataGraph(); 595 try { 596 cldGraph.classesDo(new ClassLoaderDataGraph.ClassVisitor() { 597 public void visit(Klass k) { 598 try { 599 writeHeapRecordPrologue(); 600 writeClassDumpRecord(k); 601 writeHeapRecordEpilogue(); 602 } catch (IOException e) { 603 throw new RuntimeException(e); 604 } 605 } 606 }); 607 } catch (RuntimeException re) { 608 handleRuntimeException(re); 609 } 610 } 611 writeClass(Instance instance)612 protected void writeClass(Instance instance) throws IOException { 613 Klass reflectedKlass = java_lang_Class.asKlass(instance); 614 // dump instance record only for primitive type Class objects. 615 // all other Class objects are covered by writeClassDumpRecords. 616 if (reflectedKlass == null) { 617 writeInstance(instance); 618 } 619 } 620 writeClassDumpRecord(Klass k)621 private void writeClassDumpRecord(Klass k) throws IOException { 622 out.writeByte((byte)HPROF_GC_CLASS_DUMP); 623 writeObjectID(k.getJavaMirror()); 624 out.writeInt(DUMMY_STACK_TRACE_ID); 625 Klass superKlass = k.getJavaSuper(); 626 if (superKlass != null) { 627 writeObjectID(superKlass.getJavaMirror()); 628 } else { 629 writeObjectID(null); 630 } 631 632 if (k instanceof InstanceKlass) { 633 InstanceKlass ik = (InstanceKlass) k; 634 writeObjectID(ik.getClassLoader()); 635 writeObjectID(null); // ik.getJavaMirror().getSigners()); 636 writeObjectID(null); // ik.getJavaMirror().getProtectionDomain()); 637 // two reserved id fields 638 writeObjectID(null); 639 writeObjectID(null); 640 List<Field> fields = getInstanceFields(ik); 641 int instSize = getSizeForFields(fields); 642 classDataCache.put(ik, new ClassData(instSize, fields)); 643 out.writeInt(instSize); 644 645 // For now, ignore constant pool - HAT ignores too! 646 // output number of cp entries as zero. 647 out.writeShort((short) 0); 648 649 List<Field> declaredFields = ik.getImmediateFields(); 650 List<Field> staticFields = new ArrayList<>(); 651 List<Field> instanceFields = new ArrayList<>(); 652 Iterator<Field> itr = null; 653 for (itr = declaredFields.iterator(); itr.hasNext();) { 654 Field field = itr.next(); 655 if (field.isStatic()) { 656 staticFields.add(field); 657 } else { 658 instanceFields.add(field); 659 } 660 } 661 662 // dump static field descriptors 663 writeFieldDescriptors(staticFields, ik); 664 665 // dump instance field descriptors 666 writeFieldDescriptors(instanceFields, null); 667 } else { 668 if (k instanceof ObjArrayKlass) { 669 ObjArrayKlass oak = (ObjArrayKlass) k; 670 Klass bottomKlass = oak.getBottomKlass(); 671 if (bottomKlass instanceof InstanceKlass) { 672 InstanceKlass ik = (InstanceKlass) bottomKlass; 673 writeObjectID(ik.getClassLoader()); 674 writeObjectID(null); // ik.getJavaMirror().getSigners()); 675 writeObjectID(null); // ik.getJavaMirror().getProtectionDomain()); 676 } else { 677 writeObjectID(null); 678 writeObjectID(null); 679 writeObjectID(null); 680 } 681 } else { 682 writeObjectID(null); 683 writeObjectID(null); 684 writeObjectID(null); 685 } 686 // two reserved id fields 687 writeObjectID(null); 688 writeObjectID(null); 689 // write zero instance size -- as instance size 690 // is variable for arrays. 691 out.writeInt(0); 692 // no constant pool for array klasses 693 out.writeShort((short) 0); 694 // no static fields for array klasses 695 out.writeShort((short) 0); 696 // no instance fields for array klasses 697 out.writeShort((short) 0); 698 } 699 } 700 dumpStackTraces()701 private void dumpStackTraces() throws IOException { 702 // write a HPROF_TRACE record without any frames to be referenced as object alloc sites 703 writeHeader(HPROF_TRACE, 3 * (int)INT_SIZE ); 704 out.writeInt(DUMMY_STACK_TRACE_ID); 705 out.writeInt(0); // thread number 706 out.writeInt(0); // frame count 707 708 int frameSerialNum = 0; 709 int numThreads = 0; 710 Threads threads = VM.getVM().getThreads(); 711 for (int i = 0; i < threads.getNumberOfThreads(); i++) { 712 JavaThread thread = threads.getJavaThreadAt(i); 713 Oop threadObj = thread.getThreadObj(); 714 if (threadObj != null && !thread.isExiting() && !thread.isHiddenFromExternalView()) { 715 716 // dump thread stack trace 717 ThreadStackTrace st = new ThreadStackTrace(thread); 718 st.dumpStack(-1); 719 numThreads++; 720 721 // write HPROF_FRAME records for this thread's stack trace 722 int depth = st.getStackDepth(); 723 int threadFrameStart = frameSerialNum; 724 for (int j=0; j < depth; j++) { 725 StackFrameInfo frame = st.stackFrameAt(j); 726 Method m = frame.getMethod(); 727 int classSerialNum = KlassMap.indexOf(m.getMethodHolder()) + 1; 728 // the class serial number starts from 1 729 assert classSerialNum > 0:"class not found"; 730 dumpStackFrame(++frameSerialNum, classSerialNum, m, frame.getBCI()); 731 } 732 733 // write HPROF_TRACE record for one thread 734 writeHeader(HPROF_TRACE, 3 * (int)INT_SIZE + depth * (int)VM.getVM().getOopSize()); 735 int stackSerialNum = numThreads + DUMMY_STACK_TRACE_ID; 736 out.writeInt(stackSerialNum); // stack trace serial number 737 out.writeInt(numThreads); // thread serial number 738 out.writeInt(depth); // frame count 739 for (int j=1; j <= depth; j++) { 740 writeObjectID(threadFrameStart + j); 741 } 742 } 743 } 744 } 745 dumpStackFrame(int frameSN, int classSN, Method m, int bci)746 private void dumpStackFrame(int frameSN, int classSN, Method m, int bci) throws IOException { 747 int lineNumber; 748 if (m.isNative()) { 749 lineNumber = -3; // native frame 750 } else { 751 lineNumber = m.getLineNumberFromBCI(bci); 752 } 753 // First dump UTF8 if needed 754 writeSymbol(m.getName()); // method's name 755 writeSymbol(m.getSignature()); // method's signature 756 writeSymbol(m.getMethodHolder().getSourceFileName()); // source file name 757 // Then write FRAME descriptor 758 writeHeader(HPROF_FRAME, 4 * (int)VM.getVM().getOopSize() + 2 * (int)INT_SIZE); 759 writeObjectID(frameSN); // frame serial number 760 writeSymbolID(m.getName()); // method's name 761 writeSymbolID(m.getSignature()); // method's signature 762 writeSymbolID(m.getMethodHolder().getSourceFileName()); // source file name 763 out.writeInt(classSN); // class serial number 764 out.writeInt(lineNumber); // line number 765 } 766 writeJavaThread(JavaThread jt, int index)767 protected void writeJavaThread(JavaThread jt, int index) throws IOException { 768 out.writeByte((byte) HPROF_GC_ROOT_THREAD_OBJ); 769 writeObjectID(jt.getThreadObj()); 770 out.writeInt(index); 771 out.writeInt(DUMMY_STACK_TRACE_ID); 772 writeLocalJNIHandles(jt, index); 773 } 774 writeLocalJNIHandles(JavaThread jt, int index)775 protected void writeLocalJNIHandles(JavaThread jt, int index) throws IOException { 776 final int threadIndex = index; 777 JNIHandleBlock blk = jt.activeHandles(); 778 if (blk != null) { 779 try { 780 blk.oopsDo(new AddressVisitor() { 781 public void visitAddress(Address handleAddr) { 782 try { 783 if (handleAddr != null) { 784 OopHandle oopHandle = handleAddr.getOopHandleAt(0); 785 Oop oop = objectHeap.newOop(oopHandle); 786 // exclude JNI handles hotspot internal objects 787 if (oop != null && isJavaVisible(oop)) { 788 out.writeByte((byte) HPROF_GC_ROOT_JNI_LOCAL); 789 writeObjectID(oop); 790 out.writeInt(threadIndex); 791 out.writeInt(EMPTY_FRAME_DEPTH); 792 } 793 } 794 } catch (IOException exp) { 795 throw new RuntimeException(exp); 796 } 797 } 798 public void visitCompOopAddress(Address handleAddr) { 799 throw new RuntimeException( 800 " Should not reach here. JNIHandles are not compressed \n"); 801 } 802 }); 803 } catch (RuntimeException re) { 804 handleRuntimeException(re); 805 } 806 } 807 } 808 writeGlobalJNIHandle(Address handleAddr)809 protected void writeGlobalJNIHandle(Address handleAddr) throws IOException { 810 OopHandle oopHandle = handleAddr.getOopHandleAt(0); 811 Oop oop = objectHeap.newOop(oopHandle); 812 // exclude JNI handles of hotspot internal objects 813 if (oop != null && isJavaVisible(oop)) { 814 out.writeByte((byte) HPROF_GC_ROOT_JNI_GLOBAL); 815 writeObjectID(oop); 816 // use JNIHandle address as ID 817 writeObjectID(getAddressValue(handleAddr)); 818 } 819 } 820 writeObjectArray(ObjArray array)821 protected void writeObjectArray(ObjArray array) throws IOException { 822 int headerSize = getArrayHeaderSize(true); 823 final int length = calculateArrayMaxLength(array.getLength(), 824 headerSize, 825 OBJ_ID_SIZE, 826 "Object"); 827 out.writeByte((byte) HPROF_GC_OBJ_ARRAY_DUMP); 828 writeObjectID(array); 829 out.writeInt(DUMMY_STACK_TRACE_ID); 830 out.writeInt(length); 831 writeObjectID(array.getKlass().getJavaMirror()); 832 for (int index = 0; index < length; index++) { 833 OopHandle handle = array.getOopHandleAt(index); 834 writeObjectID(getAddressValue(handle)); 835 } 836 } 837 writePrimitiveArray(TypeArray array)838 protected void writePrimitiveArray(TypeArray array) throws IOException { 839 int headerSize = getArrayHeaderSize(false); 840 TypeArrayKlass tak = (TypeArrayKlass) array.getKlass(); 841 final int type = (int) tak.getElementType(); 842 final String typeName = tak.getElementTypeName(); 843 final long typeSize = getSizeForType(type); 844 final int length = calculateArrayMaxLength(array.getLength(), 845 headerSize, 846 typeSize, 847 typeName); 848 out.writeByte((byte) HPROF_GC_PRIM_ARRAY_DUMP); 849 writeObjectID(array); 850 out.writeInt(DUMMY_STACK_TRACE_ID); 851 out.writeInt(length); 852 out.writeByte((byte) type); 853 switch (type) { 854 case TypeArrayKlass.T_BOOLEAN: 855 writeBooleanArray(array, length); 856 break; 857 case TypeArrayKlass.T_CHAR: 858 writeCharArray(array, length); 859 break; 860 case TypeArrayKlass.T_FLOAT: 861 writeFloatArray(array, length); 862 break; 863 case TypeArrayKlass.T_DOUBLE: 864 writeDoubleArray(array, length); 865 break; 866 case TypeArrayKlass.T_BYTE: 867 writeByteArray(array, length); 868 break; 869 case TypeArrayKlass.T_SHORT: 870 writeShortArray(array, length); 871 break; 872 case TypeArrayKlass.T_INT: 873 writeIntArray(array, length); 874 break; 875 case TypeArrayKlass.T_LONG: 876 writeLongArray(array, length); 877 break; 878 default: 879 throw new RuntimeException( 880 "Should not reach here: Unknown type: " + type); 881 } 882 } 883 writeBooleanArray(TypeArray array, int length)884 private void writeBooleanArray(TypeArray array, int length) throws IOException { 885 for (int index = 0; index < length; index++) { 886 long offset = BOOLEAN_BASE_OFFSET + index * BOOLEAN_SIZE; 887 out.writeBoolean(array.getHandle().getJBooleanAt(offset)); 888 } 889 } 890 writeByteArray(TypeArray array, int length)891 private void writeByteArray(TypeArray array, int length) throws IOException { 892 for (int index = 0; index < length; index++) { 893 long offset = BYTE_BASE_OFFSET + index * BYTE_SIZE; 894 out.writeByte(array.getHandle().getJByteAt(offset)); 895 } 896 } 897 writeShortArray(TypeArray array, int length)898 private void writeShortArray(TypeArray array, int length) throws IOException { 899 for (int index = 0; index < length; index++) { 900 long offset = SHORT_BASE_OFFSET + index * SHORT_SIZE; 901 out.writeShort(array.getHandle().getJShortAt(offset)); 902 } 903 } 904 writeIntArray(TypeArray array, int length)905 private void writeIntArray(TypeArray array, int length) throws IOException { 906 for (int index = 0; index < length; index++) { 907 long offset = INT_BASE_OFFSET + index * INT_SIZE; 908 out.writeInt(array.getHandle().getJIntAt(offset)); 909 } 910 } 911 writeLongArray(TypeArray array, int length)912 private void writeLongArray(TypeArray array, int length) throws IOException { 913 for (int index = 0; index < length; index++) { 914 long offset = LONG_BASE_OFFSET + index * LONG_SIZE; 915 out.writeLong(array.getHandle().getJLongAt(offset)); 916 } 917 } 918 writeCharArray(TypeArray array, int length)919 private void writeCharArray(TypeArray array, int length) throws IOException { 920 for (int index = 0; index < length; index++) { 921 long offset = CHAR_BASE_OFFSET + index * CHAR_SIZE; 922 out.writeChar(array.getHandle().getJCharAt(offset)); 923 } 924 } 925 writeFloatArray(TypeArray array, int length)926 private void writeFloatArray(TypeArray array, int length) throws IOException { 927 for (int index = 0; index < length; index++) { 928 long offset = FLOAT_BASE_OFFSET + index * FLOAT_SIZE; 929 out.writeFloat(array.getHandle().getJFloatAt(offset)); 930 } 931 } 932 writeDoubleArray(TypeArray array, int length)933 private void writeDoubleArray(TypeArray array, int length) throws IOException { 934 for (int index = 0; index < length; index++) { 935 long offset = DOUBLE_BASE_OFFSET + index * DOUBLE_SIZE; 936 out.writeDouble(array.getHandle().getJDoubleAt(offset)); 937 } 938 } 939 writeInstance(Instance instance)940 protected void writeInstance(Instance instance) throws IOException { 941 Klass klass = instance.getKlass(); 942 if (klass.getClassLoaderData() == null) { 943 // Ignoring this object since the corresponding Klass is not loaded. 944 // Might be a dormant archive object. 945 return; 946 } 947 948 out.writeByte((byte) HPROF_GC_INSTANCE_DUMP); 949 writeObjectID(instance); 950 out.writeInt(DUMMY_STACK_TRACE_ID); 951 writeObjectID(klass.getJavaMirror()); 952 953 ClassData cd = (ClassData) classDataCache.get(klass); 954 955 if (Assert.ASSERTS_ENABLED) { 956 Assert.that(cd != null, "can not get class data for " + klass.getName().asString() + klass.getAddress()); 957 } 958 List<Field> fields = cd.fields; 959 int size = cd.instSize; 960 out.writeInt(size); 961 for (Iterator<Field> itr = fields.iterator(); itr.hasNext();) { 962 writeField(itr.next(), instance); 963 } 964 } 965 966 //-- Internals only below this point 967 writeFieldDescriptors(List<Field> fields, InstanceKlass ik)968 private void writeFieldDescriptors(List<Field> fields, InstanceKlass ik) 969 throws IOException { 970 // ik == null for instance fields. 971 out.writeShort((short) fields.size()); 972 for (Iterator<Field> itr = fields.iterator(); itr.hasNext();) { 973 Field field = itr.next(); 974 Symbol name = field.getName(); 975 writeSymbolID(name); 976 char typeCode = (char) field.getSignature().getByteAt(0); 977 int kind = signatureToHprofKind(typeCode); 978 out.writeByte((byte)kind); 979 if (ik != null) { 980 // static field 981 writeField(field, ik.getJavaMirror()); 982 } 983 } 984 } 985 signatureToHprofKind(char ch)986 public static int signatureToHprofKind(char ch) { 987 switch (ch) { 988 case JVM_SIGNATURE_CLASS: 989 case JVM_SIGNATURE_ARRAY: 990 return HPROF_NORMAL_OBJECT; 991 case JVM_SIGNATURE_BOOLEAN: 992 return HPROF_BOOLEAN; 993 case JVM_SIGNATURE_CHAR: 994 return HPROF_CHAR; 995 case JVM_SIGNATURE_FLOAT: 996 return HPROF_FLOAT; 997 case JVM_SIGNATURE_DOUBLE: 998 return HPROF_DOUBLE; 999 case JVM_SIGNATURE_BYTE: 1000 return HPROF_BYTE; 1001 case JVM_SIGNATURE_SHORT: 1002 return HPROF_SHORT; 1003 case JVM_SIGNATURE_INT: 1004 return HPROF_INT; 1005 case JVM_SIGNATURE_LONG: 1006 return HPROF_LONG; 1007 default: 1008 throw new RuntimeException("should not reach here"); 1009 } 1010 } 1011 writeField(Field field, Oop oop)1012 private void writeField(Field field, Oop oop) throws IOException { 1013 char typeCode = (char) field.getSignature().getByteAt(0); 1014 switch (typeCode) { 1015 case JVM_SIGNATURE_BOOLEAN: 1016 out.writeBoolean(((BooleanField)field).getValue(oop)); 1017 break; 1018 case JVM_SIGNATURE_CHAR: 1019 out.writeChar(((CharField)field).getValue(oop)); 1020 break; 1021 case JVM_SIGNATURE_BYTE: 1022 out.writeByte(((ByteField)field).getValue(oop)); 1023 break; 1024 case JVM_SIGNATURE_SHORT: 1025 out.writeShort(((ShortField)field).getValue(oop)); 1026 break; 1027 case JVM_SIGNATURE_INT: 1028 out.writeInt(((IntField)field).getValue(oop)); 1029 break; 1030 case JVM_SIGNATURE_LONG: 1031 out.writeLong(((LongField)field).getValue(oop)); 1032 break; 1033 case JVM_SIGNATURE_FLOAT: 1034 out.writeFloat(((FloatField)field).getValue(oop)); 1035 break; 1036 case JVM_SIGNATURE_DOUBLE: 1037 out.writeDouble(((DoubleField)field).getValue(oop)); 1038 break; 1039 case JVM_SIGNATURE_CLASS: 1040 case JVM_SIGNATURE_ARRAY: { 1041 if (VM.getVM().isCompressedOopsEnabled()) { 1042 OopHandle handle = ((NarrowOopField)field).getValueAsOopHandle(oop); 1043 writeObjectID(getAddressValue(handle)); 1044 } else { 1045 OopHandle handle = ((OopField)field).getValueAsOopHandle(oop); 1046 writeObjectID(getAddressValue(handle)); 1047 } 1048 break; 1049 } 1050 default: 1051 throw new RuntimeException("should not reach here"); 1052 } 1053 } 1054 writeHeader(int tag, int len)1055 private void writeHeader(int tag, int len) throws IOException { 1056 out.writeByte((byte)tag); 1057 out.writeInt(0); // current ticks 1058 out.writeInt(len); 1059 } 1060 writeDummyTrace()1061 private void writeDummyTrace() throws IOException { 1062 writeHeader(HPROF_TRACE, 3 * 4); 1063 out.writeInt(DUMMY_STACK_TRACE_ID); 1064 out.writeInt(0); 1065 out.writeInt(0); 1066 } 1067 writeClassSymbols(Klass k)1068 private void writeClassSymbols(Klass k) throws IOException { 1069 writeSymbol(k.getName()); 1070 if (k instanceof InstanceKlass) { 1071 InstanceKlass ik = (InstanceKlass) k; 1072 List<Field> declaredFields = ik.getImmediateFields(); 1073 for (Iterator<Field> itr = declaredFields.iterator(); itr.hasNext();) { 1074 Field field = itr.next(); 1075 writeSymbol(field.getName()); 1076 } 1077 } 1078 } 1079 writeSymbols()1080 private void writeSymbols() throws IOException { 1081 // Write all the symbols that are used by the classes 1082 ClassLoaderDataGraph cldGraph = VM.getVM().getClassLoaderDataGraph(); 1083 try { 1084 cldGraph.classesDo(new ClassLoaderDataGraph.ClassVisitor() { 1085 public void visit(Klass k) { 1086 try { 1087 writeClassSymbols(k); 1088 } catch (IOException e) { 1089 throw new RuntimeException(e); 1090 } 1091 } 1092 }); 1093 } catch (RuntimeException re) { 1094 handleRuntimeException(re); 1095 } 1096 } 1097 writeSymbol(Symbol sym)1098 private void writeSymbol(Symbol sym) throws IOException { 1099 // If name is already written don't write it again. 1100 if (names.add(sym)) { 1101 if(sym != null) { 1102 byte[] buf = sym.asString().getBytes("UTF-8"); 1103 writeHeader(HPROF_UTF8, buf.length + OBJ_ID_SIZE); 1104 writeSymbolID(sym); 1105 out.write(buf); 1106 } else { 1107 writeHeader(HPROF_UTF8, 0 + OBJ_ID_SIZE); 1108 writeSymbolID(null); 1109 } 1110 } 1111 } 1112 writeClasses()1113 private void writeClasses() throws IOException { 1114 // write class list (id, name) association 1115 ClassLoaderDataGraph cldGraph = VM.getVM().getClassLoaderDataGraph(); 1116 try { 1117 cldGraph.classesDo(new ClassLoaderDataGraph.ClassVisitor() { 1118 public void visit(Klass k) { 1119 try { 1120 Instance clazz = k.getJavaMirror(); 1121 writeHeader(HPROF_LOAD_CLASS, 2 * (OBJ_ID_SIZE + 4)); 1122 out.writeInt(serialNum); 1123 writeObjectID(clazz); 1124 KlassMap.add(serialNum - 1, k); 1125 out.writeInt(DUMMY_STACK_TRACE_ID); 1126 writeSymbolID(k.getName()); 1127 serialNum++; 1128 } catch (IOException exp) { 1129 throw new RuntimeException(exp); 1130 } 1131 } 1132 }); 1133 } catch (RuntimeException re) { 1134 handleRuntimeException(re); 1135 } 1136 } 1137 1138 // writes hprof binary file header writeFileHeader()1139 private void writeFileHeader() throws IOException { 1140 // version string 1141 out.writeBytes(HPROF_HEADER_1_0_2); 1142 out.writeByte((byte)'\0'); 1143 1144 // write identifier size. we use pointers as identifiers. 1145 out.writeInt(OBJ_ID_SIZE); 1146 1147 // timestamp -- file creation time. 1148 out.writeLong(System.currentTimeMillis()); 1149 } 1150 1151 // writes unique ID for an object writeObjectID(Oop oop)1152 private void writeObjectID(Oop oop) throws IOException { 1153 OopHandle handle = (oop != null)? oop.getHandle() : null; 1154 long address = getAddressValue(handle); 1155 writeObjectID(address); 1156 } 1157 writeSymbolID(Symbol sym)1158 private void writeSymbolID(Symbol sym) throws IOException { 1159 assert names.contains(sym); 1160 long address = (sym != null) ? getAddressValue(sym.getAddress()) : getAddressValue(null); 1161 writeObjectID(address); 1162 } 1163 writeObjectID(long address)1164 private void writeObjectID(long address) throws IOException { 1165 if (OBJ_ID_SIZE == 4) { 1166 out.writeInt((int) address); 1167 } else { 1168 out.writeLong(address); 1169 } 1170 } 1171 getAddressValue(Address addr)1172 private long getAddressValue(Address addr) { 1173 return (addr == null)? 0L : dbg.getAddressValue(addr); 1174 } 1175 1176 // get all declared as well as inherited (directly/indirectly) fields getInstanceFields(InstanceKlass ik)1177 private static List<Field> getInstanceFields(InstanceKlass ik) { 1178 InstanceKlass klass = ik; 1179 List<Field> res = new ArrayList<>(); 1180 while (klass != null) { 1181 List<Field> curFields = klass.getImmediateFields(); 1182 for (Iterator<Field> itr = curFields.iterator(); itr.hasNext();) { 1183 Field f = itr.next(); 1184 if (! f.isStatic()) { 1185 res.add(f); 1186 } 1187 } 1188 klass = (InstanceKlass) klass.getSuper(); 1189 } 1190 return res; 1191 } 1192 1193 // get size in bytes (in stream) required for given fields. Note 1194 // that this is not the same as object size in heap. The size in 1195 // heap will include size of padding/alignment bytes as well. getSizeForFields(List<Field> fields)1196 private int getSizeForFields(List<Field> fields) { 1197 int size = 0; 1198 for (Iterator<Field> itr = fields.iterator(); itr.hasNext();) { 1199 Field field = itr.next(); 1200 char typeCode = (char) field.getSignature().getByteAt(0); 1201 switch (typeCode) { 1202 case JVM_SIGNATURE_BOOLEAN: 1203 case JVM_SIGNATURE_BYTE: 1204 size++; 1205 break; 1206 case JVM_SIGNATURE_CHAR: 1207 case JVM_SIGNATURE_SHORT: 1208 size += 2; 1209 break; 1210 case JVM_SIGNATURE_INT: 1211 case JVM_SIGNATURE_FLOAT: 1212 size += 4; 1213 break; 1214 case JVM_SIGNATURE_CLASS: 1215 case JVM_SIGNATURE_ARRAY: 1216 size += OBJ_ID_SIZE; 1217 break; 1218 case JVM_SIGNATURE_LONG: 1219 case JVM_SIGNATURE_DOUBLE: 1220 size += 8; 1221 break; 1222 default: 1223 throw new RuntimeException("should not reach here"); 1224 } 1225 } 1226 return size; 1227 } 1228 1229 // We don't have allocation site info. We write a dummy 1230 // stack trace with this id. 1231 private static final int DUMMY_STACK_TRACE_ID = 1; 1232 private static final int EMPTY_FRAME_DEPTH = -1; 1233 1234 private DataOutputStream out; 1235 private FileOutputStream fos; 1236 private Debugger dbg; 1237 private ObjectHeap objectHeap; 1238 private ArrayList<Klass> KlassMap; 1239 1240 // oopSize of the debuggee 1241 private int OBJ_ID_SIZE; 1242 1243 // Added for hprof file format 1.0.2 support 1244 private boolean useSegmentedHeapDump; 1245 private long currentSegmentStart; 1246 1247 private long BOOLEAN_BASE_OFFSET; 1248 private long BYTE_BASE_OFFSET; 1249 private long CHAR_BASE_OFFSET; 1250 private long SHORT_BASE_OFFSET; 1251 private long INT_BASE_OFFSET; 1252 private long LONG_BASE_OFFSET; 1253 private long FLOAT_BASE_OFFSET; 1254 private long DOUBLE_BASE_OFFSET; 1255 private long OBJECT_BASE_OFFSET; 1256 1257 private long BOOLEAN_SIZE; 1258 private long BYTE_SIZE; 1259 private long CHAR_SIZE; 1260 private long SHORT_SIZE; 1261 private long INT_SIZE; 1262 private long LONG_SIZE; 1263 private long FLOAT_SIZE; 1264 private long DOUBLE_SIZE; 1265 1266 private static class ClassData { 1267 int instSize; 1268 List<Field> fields; 1269 ClassData(int instSize, List<Field> fields)1270 ClassData(int instSize, List<Field> fields) { 1271 this.instSize = instSize; 1272 this.fields = fields; 1273 } 1274 } 1275 1276 private Map<InstanceKlass, ClassData> classDataCache = new HashMap<>(); 1277 } 1278