< prev index next >

test/lib/jdk/test/lib/hprof/model/JavaValueArray.java

Print this page
@@ -34,53 +34,31 @@
  
  import java.io.IOException;
  import java.util.Objects;
  
  /**
-  * An array of values, that is, an array of ints, boolean, floats or the like.
+  * 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 String arrayTypeName(byte sig) {
-         switch (sig) {
+     private static int elementSize(byte type) {
+         switch (type) {
              case 'B':
-                 return "byte[]";
              case 'Z':
-                 return "boolean[]";
+                 return 1;
              case 'C':
-                 return "char[]";
              case 'S':
-                 return "short[]";
+                 return 2;
              case 'I':
-                 return "int[]";
              case 'F':
-                 return "float[]";
+                 return 4;
              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 T_BYTE:
-             case T_BOOLEAN:
-                 return 1;
-             case T_CHAR:
-             case T_SHORT:
-                 return 2;
-             case T_INT:
-             case T_FLOAT:
-                 return 4;
-             case T_LONG:
-             case T_DOUBLE:
                  return 8;
              default:
                  throw new RuntimeException("invalid array element type: " + type);
          }
      }

@@ -99,11 +77,11 @@
      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());
+         return len * elementSize(getRealElementType());
      }
  
      private long dataStartOffset() {
          return getOffset() + idSize() + 4 + 4 + 1;
      }

@@ -171,20 +149,29 @@
                                    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;

@@ -196,32 +183,58 @@
      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) {
+     // 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 elementSig = getElementType();
-         clazz = snapshot.findClass(arrayTypeName(elementSig));
-         if (clazz == null) {
-             clazz = snapshot.getArrayClass("" + ((char) elementSig));
+ 
+         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() {

@@ -243,10 +256,13 @@
                  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);

@@ -257,10 +273,14 @@
      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());

@@ -279,11 +299,11 @@
      public String valueString(boolean bigLimit) {
          // Char arrays deserve special treatment
          StringBuilder result;
          JavaThing[] things = getValue();
          byte elementSignature = getElementType();
-         if (elementSignature == 'C')  {
+         if (elementSignature == 'C' && !isFlatArray())  {
              result = new StringBuilder();
              for (int i = 0; i < things.length; i++) {
                  result.append(things[i]);
              }
          } else {

@@ -338,10 +358,14 @@
                      case 'D': {         // double
                          double val = ((JavaDouble)things[i]).value;
                          result.append(val);
                          break;
                      }
+                     case 'Q': {
+                         InlinedJavaObject obj = (InlinedJavaObject)things[i];
+                         result.append(obj);
+                     }
                      default: {
                          throw new RuntimeException("unknown primitive type?");
                      }
                  }
              }
< prev index next >