574 /** 575 * This class represents the field information for one field contained in the fields array of an 576 * {@code InstanceKlass}. The implementation is similar to the native {@code FieldInfo} class. 577 */ 578 private class FieldInfo { 579 /** 580 * Native pointer into the array of Java shorts. 581 */ 582 private final long metaspaceData; 583 584 /** 585 * Creates a field info for the field in the fields array at index {@code index}. 586 * 587 * @param index index to the fields array 588 */ 589 FieldInfo(int index) { 590 HotSpotVMConfig config = config(); 591 // Get Klass::_fields 592 final long metaspaceFields = UNSAFE.getAddress(getMetaspaceKlass() + config.instanceKlassFieldsOffset); 593 assert config.fieldInfoFieldSlots == 6 : "revisit the field parsing code"; 594 metaspaceData = metaspaceFields + config.arrayU2DataOffset + config.fieldInfoFieldSlots * Short.BYTES * index; 595 } 596 597 private int getAccessFlags() { 598 return readFieldSlot(config().fieldInfoAccessFlagsOffset); 599 } 600 601 private int getNameIndex() { 602 return readFieldSlot(config().fieldInfoNameIndexOffset); 603 } 604 605 private int getSignatureIndex() { 606 return readFieldSlot(config().fieldInfoSignatureIndexOffset); 607 } 608 609 public int getOffset() { 610 HotSpotVMConfig config = config(); 611 final int lowPacked = readFieldSlot(config.fieldInfoLowPackedOffset); 612 final int highPacked = readFieldSlot(config.fieldInfoHighPackedOffset); 613 final int offset = ((highPacked << Short.SIZE) | lowPacked) >> config.fieldInfoTagSize; 614 return offset; 615 } 616 617 /** 618 * Helper method to read an entry (slot) from the field array. Currently field info is laid 619 * on top an array of Java shorts. 620 */ 621 private int readFieldSlot(int index) { 622 return UNSAFE.getChar(metaspaceData + Short.BYTES * index); 623 } 624 625 /** 626 * Returns the name of this field as a {@link String}. If the field is an internal field the 627 * name index is pointing into the vmSymbols table. 628 */ 629 public String getName() { 630 final int nameIndex = getNameIndex(); 631 return isInternal() ? HotSpotVmSymbols.symbolAt(nameIndex) : getConstantPool().lookupUtf8(nameIndex); 632 } 633 634 /** 635 * Returns the signature of this field as {@link String}. If the field is an internal field 636 * the signature index is pointing into the vmSymbols table. 637 */ 638 public String getSignature() { 639 final int signatureIndex = getSignatureIndex(); 640 return isInternal() ? HotSpotVmSymbols.symbolAt(signatureIndex) : getConstantPool().lookupUtf8(signatureIndex); 641 } 642 643 public JavaType getType() { 644 String signature = getSignature(); 645 return runtime().lookupType(signature, HotSpotResolvedObjectTypeImpl.this, false); 646 } 647 648 private boolean isInternal() { 649 return (getAccessFlags() & config().jvmAccFieldInternal) != 0; 650 } 651 652 public boolean isStatic() { 653 return Modifier.isStatic(getAccessFlags()); 654 } 655 656 public boolean hasGenericSignature() { 657 return (getAccessFlags() & config().jvmAccFieldHasGenericSignature) != 0; 658 } 659 } 660 661 private static class OffsetComparator implements java.util.Comparator<HotSpotResolvedJavaField> { 662 @Override 663 public int compare(HotSpotResolvedJavaField o1, HotSpotResolvedJavaField o2) { 664 return o1.offset() - o2.offset(); 665 } 666 } 667 668 @Override 669 public ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses) { 670 if (instanceFields == null) { 671 if (isArray() || isInterface()) { 672 instanceFields = new HotSpotResolvedJavaField[0]; 673 } else { 674 final int fieldCount = getFieldCount(); 675 ArrayList<HotSpotResolvedJavaField> fieldsArray = new ArrayList<>(fieldCount); 676 677 for (int i = 0; i < fieldCount; i++) { 678 FieldInfo field = new FieldInfo(i); 679 680 // We are only interested in instance fields. | 574 /** 575 * This class represents the field information for one field contained in the fields array of an 576 * {@code InstanceKlass}. The implementation is similar to the native {@code FieldInfo} class. 577 */ 578 private class FieldInfo { 579 /** 580 * Native pointer into the array of Java shorts. 581 */ 582 private final long metaspaceData; 583 584 /** 585 * Creates a field info for the field in the fields array at index {@code index}. 586 * 587 * @param index index to the fields array 588 */ 589 FieldInfo(int index) { 590 HotSpotVMConfig config = config(); 591 // Get Klass::_fields 592 final long metaspaceFields = UNSAFE.getAddress(getMetaspaceKlass() + config.instanceKlassFieldsOffset); 593 assert config.fieldInfoFieldSlots == 6 : "revisit the field parsing code"; 594 int offset = config.fieldInfoFieldSlots * Short.BYTES * index; 595 metaspaceData = metaspaceFields + config.arrayU2DataOffset + offset; 596 } 597 598 private int getAccessFlags() { 599 return readFieldSlot(config().fieldInfoAccessFlagsOffset); 600 } 601 602 private int getNameIndex() { 603 return readFieldSlot(config().fieldInfoNameIndexOffset); 604 } 605 606 private int getSignatureIndex() { 607 return readFieldSlot(config().fieldInfoSignatureIndexOffset); 608 } 609 610 public int getOffset() { 611 HotSpotVMConfig config = config(); 612 final int lowPacked = readFieldSlot(config.fieldInfoLowPackedOffset); 613 final int highPacked = readFieldSlot(config.fieldInfoHighPackedOffset); 614 final int offset = ((highPacked << Short.SIZE) | lowPacked) >> config.fieldInfoTagSize; 615 return offset; 616 } 617 618 /** 619 * Helper method to read an entry (slot) from the field array. Currently field info is laid 620 * on top an array of Java shorts. 621 */ 622 private int readFieldSlot(int index) { 623 int offset = Short.BYTES * index; 624 return UNSAFE.getChar(metaspaceData + offset); 625 } 626 627 /** 628 * Returns the name of this field as a {@link String}. If the field is an internal field the 629 * name index is pointing into the vmSymbols table. 630 */ 631 public String getName() { 632 final int nameIndex = getNameIndex(); 633 return isInternal() ? config().symbolAt(nameIndex) : getConstantPool().lookupUtf8(nameIndex); 634 } 635 636 /** 637 * Returns the signature of this field as {@link String}. If the field is an internal field 638 * the signature index is pointing into the vmSymbols table. 639 */ 640 public String getSignature() { 641 final int signatureIndex = getSignatureIndex(); 642 return isInternal() ? config().symbolAt(signatureIndex) : getConstantPool().lookupUtf8(signatureIndex); 643 } 644 645 public JavaType getType() { 646 String signature = getSignature(); 647 return runtime().lookupType(signature, HotSpotResolvedObjectTypeImpl.this, false); 648 } 649 650 private boolean isInternal() { 651 return (getAccessFlags() & config().jvmAccFieldInternal) != 0; 652 } 653 654 public boolean isStatic() { 655 return Modifier.isStatic(getAccessFlags()); 656 } 657 658 public boolean hasGenericSignature() { 659 return (getAccessFlags() & config().jvmAccFieldHasGenericSignature) != 0; 660 } 661 } 662 663 @SuppressFBWarnings(value = "SE_COMPARATOR_SHOULD_BE_SERIALIZABLE", justification = "comparator is only used transiently") 664 private static class OffsetComparator implements java.util.Comparator<HotSpotResolvedJavaField> { 665 @Override 666 public int compare(HotSpotResolvedJavaField o1, HotSpotResolvedJavaField o2) { 667 return o1.offset() - o2.offset(); 668 } 669 } 670 671 @Override 672 public ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses) { 673 if (instanceFields == null) { 674 if (isArray() || isInterface()) { 675 instanceFields = new HotSpotResolvedJavaField[0]; 676 } else { 677 final int fieldCount = getFieldCount(); 678 ArrayList<HotSpotResolvedJavaField> fieldsArray = new ArrayList<>(fieldCount); 679 680 for (int i = 0; i < fieldCount; i++) { 681 FieldInfo field = new FieldInfo(i); 682 683 // We are only interested in instance fields. |