< prev index next > test/lib/jdk/test/lib/hprof/model/JavaValueArray.java
Print this page
import java.io.IOException;
import java.nio.ByteOrder;
import java.util.Objects;
/**
! * An array of values, that is, an array of ints, boolean, floats or the like.
*
* @author Bill Foote
*/
public class JavaValueArray extends JavaLazyReadObject
/*imports*/ implements ArrayTypeCodes {
- private static String arrayTypeName(byte sig) {
- switch (sig) {
- case 'B':
- return "byte[]";
- case 'Z':
- return "boolean[]";
- case 'C':
- return "char[]";
- case 'S':
- return "short[]";
- case 'I':
- return "int[]";
- case 'F':
- return "float[]";
- case 'J':
- return "long[]";
- case 'D':
- return "double[]";
- default:
- throw new RuntimeException("invalid array element sig: " + sig);
- }
- }
-
private static int elementSize(byte type) {
switch (type) {
case 'B':
case 'Z':
return 1;
import java.io.IOException;
import java.nio.ByteOrder;
import java.util.Objects;
/**
! * An array of values, that is, an array of ints, boolean, floats, etc.
+ * or flat array of primitive objects.
*
* @author Bill Foote
*/
public class JavaValueArray extends JavaLazyReadObject
/*imports*/ implements ArrayTypeCodes {
private static int elementSize(byte type) {
switch (type) {
case 'B':
case 'Z':
return 1;
protected final long readValueLength() throws IOException {
long offset = getOffset() + idSize() + 4;
// length of the array in elements
long len = buf().getInt(offset);
// byte length of array
! return len * elementSize(getElementType());
}
private long dataStartOffset() {
return getOffset() + idSize() + 4 + 4 + 1;
}
protected final long readValueLength() throws IOException {
long offset = getOffset() + idSize() + 4;
// length of the array in elements
long len = buf().getInt(offset);
// byte length of array
! return len * elementSize(getRealElementType());
}
private long dataStartOffset() {
return getOffset() + idSize() + 4 + 4 + 1;
}
res[i] = new JavaDouble(doubleAt(offset));
offset += 8;
}
return res;
}
+ case 'Q': {
+ for (int i = 0; i < len; i++) {
+ res[i] = new InlinedJavaObject(flatArrayElementClass, offset);
+ offset += flatArrayElementClass.getInlinedInstanceSize();
+ }
+ return res;
+ }
default: {
throw new RuntimeException("unknown primitive type?");
}
}
}
}
// JavaClass set only after resolve.
private JavaClass clazz;
+ private long objID;
+
// This field contains elementSignature byte and
// divider to be used to calculate length. Note that
// length of content byte[] is not same as array length.
// Actual array length is (byte[].length / divider)
private int data;
private static final int LENGTH_DIVIDER_MASK = 0x0FF00;
// Number of bits to shift to get length divider
private static final int LENGTH_DIVIDER_SHIFT = 8;
! public JavaValueArray(byte elementSignature, long offset) {
super(offset);
this.data = (elementSignature & SIGNATURE_MASK);
}
public JavaClass getClazz() {
return clazz;
}
public void visitReferencedObjects(JavaHeapObjectVisitor v) {
super.visitReferencedObjects(v);
}
public void resolve(Snapshot snapshot) {
if (clazz instanceof JavaClass) {
return;
}
! byte elementSig = getElementType();
! clazz = snapshot.findClass(arrayTypeName(elementSig));
! if (clazz == null) {
! clazz = snapshot.getArrayClass("" + ((char) elementSig));
}
getClazz().addInstance(this);
super.resolve(snapshot);
}
public int getLength() {
private static final int LENGTH_DIVIDER_MASK = 0x0FF00;
// Number of bits to shift to get length divider
private static final int LENGTH_DIVIDER_SHIFT = 8;
! // Flat array support.
+ private JavaClass flatArrayElementClass;
+
+ public JavaValueArray(long id, byte elementSignature, long offset) {
super(offset);
+ this.objID = id;
this.data = (elementSignature & SIGNATURE_MASK);
}
public JavaClass getClazz() {
return clazz;
}
+ public boolean isFlatArray() {
+ return flatArrayElementClass != null;
+ }
+
+ public JavaClass getFlatElementClazz() {
+ return flatArrayElementClass;
+ }
+
public void visitReferencedObjects(JavaHeapObjectVisitor v) {
super.visitReferencedObjects(v);
}
public void resolve(Snapshot snapshot) {
if (clazz instanceof JavaClass) {
return;
}
!
! byte elementType = getElementType();
! String elementSig = "" + (char)elementType;
! // Check if this is a flat array of primitive objects.
+ Number elementClassID = snapshot.findFlatArrayElementType(objID);
+ if (elementClassID != null) {
+ // This is flat array.
+ JavaHeapObject elementClazz = snapshot.findThing(getIdValue(elementClassID));
+ if (elementClazz instanceof JavaClass elementJavaClazz) {
+ flatArrayElementClass = elementJavaClazz;
+ // need to resolve the element class
+ flatArrayElementClass.resolve(snapshot);
+ elementSig = "Q" + flatArrayElementClass.getName() + ";";
+ } else {
+ // The class not found.
+ System.out.println("WARNING: flat array element class not found");
+ }
}
+ clazz = snapshot.getArrayClass(elementSig);
getClazz().addInstance(this);
super.resolve(snapshot);
}
public int getLength() {
break;
case 'J':
case 'D':
divider = 8;
break;
+ case 'Q':
+ divider = flatArrayElementClass.getInlinedInstanceSize();
+ break;
default:
throw new RuntimeException("unknown primitive type: " +
elementSignature);
}
data |= (divider << LENGTH_DIVIDER_SHIFT);
public JavaThing[] getElements() {
return getValue();
}
public byte getElementType() {
+ return isFlatArray() ? (byte)'Q' : getRealElementType();
+ }
+
+ private byte getRealElementType() {
return (byte) (data & SIGNATURE_MASK);
}
private void checkIndex(int index) {
Objects.checkIndex(index, getLength());
public String valueString(boolean bigLimit) {
// Char arrays deserve special treatment
StringBuilder result;
JavaThing[] things = getValue();
byte elementSignature = getElementType();
! if (elementSignature == 'C') {
result = new StringBuilder();
for (int i = 0; i < things.length; i++) {
result.append(things[i]);
}
} else {
public String valueString(boolean bigLimit) {
// Char arrays deserve special treatment
StringBuilder result;
JavaThing[] things = getValue();
byte elementSignature = getElementType();
! if (elementSignature == 'C' && !isFlatArray()) {
result = new StringBuilder();
for (int i = 0; i < things.length; i++) {
result.append(things[i]);
}
} else {
< prev index next >