< prev index next >

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

Print this page

 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 /*
 26  * The Original Code is HAT. The Initial Developer of the
 27  * Original Code is Bill Foote, with contributions from others
 28  * at JavaSoft/Sun.
 29  */
 30 
 31 package jdk.test.lib.hprof.model;
 32 
 33 import java.io.IOException;
 34 import java.nio.ByteOrder;
 35 import java.util.Objects;
 36 
 37 /**
 38  * An array of values, that is, an array of ints, boolean, floats or the like.

 39  *
 40  * @author      Bill Foote
 41  */
 42 public class JavaValueArray extends JavaLazyReadObject
 43                 /*imports*/ implements ArrayTypeCodes {
 44 
 45     private static String arrayTypeName(byte sig) {
 46         switch (sig) {
 47             case 'B':
 48                 return "byte[]";
 49             case 'Z':
 50                 return "boolean[]";
 51             case 'C':
 52                 return "char[]";
 53             case 'S':
 54                 return "short[]";
 55             case 'I':
 56                 return "int[]";
 57             case 'F':
 58                 return "float[]";
 59             case 'J':
 60                 return "long[]";
 61             case 'D':
 62                 return "double[]";
 63             default:
 64                 throw new RuntimeException("invalid array element sig: " + sig);
 65         }
 66     }
 67 
 68     private static int elementSize(byte type) {
 69         switch (type) {
 70             case 'B':
 71             case 'Z':
 72                 return 1;
 73             case 'C':
 74             case 'S':
 75                 return 2;
 76             case 'I':
 77             case 'F':
 78                 return 4;
 79             case 'J':
 80             case 'D':
 81                 return 8;
 82             default:
 83                 throw new RuntimeException("invalid array element type: " + type);
 84         }
 85     }
 86 
 87     /*
 88      * Java primitive array record (HPROF_GC_PRIM_ARRAY_DUMP) looks
 89      * as below:
 90      *
 91      *    object ID
 92      *    stack trace serial number (int)
 93      *    number of elements (int)
 94      *    element type (byte)
 95      *    array data
 96      */
 97     @Override
 98     protected final long readValueLength() throws IOException {
 99         long offset = getOffset() + idSize() + 4;
100         // length of the array in elements
101         long len = buf().getInt(offset);
102         // byte length of array
103         return len * elementSize(getElementType());
104     }
105 
106     private long dataStartOffset() {
107         return getOffset() + idSize() + 4 + 4 + 1;
108     }
109 
110 
111     @Override
112     protected final JavaThing[] readValue() throws IOException {
113         int len = getLength();
114         long offset = dataStartOffset();
115 
116         JavaThing[] res = new JavaThing[len];
117         synchronized (buf()) {
118             switch (getElementType()) {
119                 case 'Z': {
120                               for (int i = 0; i < len; i++) {
121                                   res[i] = new JavaBoolean(booleanAt(offset));
122                                   offset += 1;
123                               }

155                               for (int i = 0; i < len; i++) {
156                                   res[i] = new JavaLong(longAt(offset));
157                                   offset += 8;
158                               }
159                               return res;
160                 }
161                 case 'F': {
162                               for (int i = 0; i < len; i++) {
163                                   res[i] = new JavaFloat(floatAt(offset));
164                                   offset += 4;
165                               }
166                               return res;
167                 }
168                 case 'D': {
169                               for (int i = 0; i < len; i++) {
170                                   res[i] = new JavaDouble(doubleAt(offset));
171                                   offset += 8;
172                               }
173                               return res;
174                 }







175                 default: {
176                              throw new RuntimeException("unknown primitive type?");
177                 }
178             }
179         }
180     }
181 
182     // JavaClass set only after resolve.
183     private JavaClass clazz;
184 


185     // This field contains elementSignature byte and
186     // divider to be used to calculate length. Note that
187     // length of content byte[] is not same as array length.
188     // Actual array length is (byte[].length / divider)
189     private int data;
190 
191     // First 8 bits of data is used for element signature
192     private static final int SIGNATURE_MASK = 0x0FF;
193 
194     // Next 8 bits of data is used for length divider
195     private static final int LENGTH_DIVIDER_MASK = 0x0FF00;
196 
197     // Number of bits to shift to get length divider
198     private static final int LENGTH_DIVIDER_SHIFT = 8;
199 
200     public JavaValueArray(byte elementSignature, long offset) {



201         super(offset);

202         this.data = (elementSignature & SIGNATURE_MASK);
203     }
204 
205     public JavaClass getClazz() {
206         return clazz;
207     }
208 








209     public void visitReferencedObjects(JavaHeapObjectVisitor v) {
210         super.visitReferencedObjects(v);
211     }
212 
213     public void resolve(Snapshot snapshot) {
214         if (clazz instanceof JavaClass) {
215             return;
216         }
217         byte elementSig = getElementType();
218         clazz = snapshot.findClass(arrayTypeName(elementSig));
219         if (clazz == null) {
220             clazz = snapshot.getArrayClass("" + ((char) elementSig));













221         }

222         getClazz().addInstance(this);
223         super.resolve(snapshot);
224     }
225 
226     public int getLength() {
227         int divider = (data & LENGTH_DIVIDER_MASK) >>> LENGTH_DIVIDER_SHIFT;
228         if (divider == 0) {
229             byte elementSignature = getElementType();
230             switch (elementSignature) {
231             case 'B':
232             case 'Z':
233                 divider = 1;
234                 break;
235             case 'C':
236             case 'S':
237                 divider = 2;
238                 break;
239             case 'I':
240             case 'F':
241                 divider = 4;
242                 break;
243             case 'J':
244             case 'D':
245                 divider = 8;
246                 break;



247             default:
248                 throw new RuntimeException("unknown primitive type: " +
249                                 elementSignature);
250             }
251             data |= (divider << LENGTH_DIVIDER_SHIFT);
252         }
253         return (int)(getValueLength() / divider);
254     }
255 
256     public JavaThing[] getElements() {
257         return getValue();
258     }
259 
260     public byte getElementType() {




261         return (byte) (data & SIGNATURE_MASK);
262     }
263 
264     private void checkIndex(int index) {
265         Objects.checkIndex(index, getLength());
266     }
267 
268     private void requireType(char type) {
269         if (getElementType() != type) {
270             throw new RuntimeException("not of type : " + type);
271         }
272     }
273 
274     public String valueString() {
275         return valueString(true);
276     }
277 
278     public String valueString(boolean bigLimit) {
279         // Char arrays deserve special treatment
280         StringBuilder result;
281         JavaThing[] things = getValue();
282         byte elementSignature = getElementType();
283         if (elementSignature == 'C')  {
284             result = new StringBuilder();
285             for (int i = 0; i < things.length; i++) {
286                 result.append(things[i]);
287             }
288         } else {
289             int limit = 8;
290             if (bigLimit) {
291                 limit = 1000;
292             }
293             result = new StringBuilder("{");
294             for (int i = 0; i < things.length; i++) {
295                 if (i > 0) {
296                     result.append(", ");
297                 }
298                 if (i >= limit) {
299                     result.append("... ");
300                     break;
301                 }
302                 switch (elementSignature) {
303                     case 'Z': {

 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 /*
 26  * The Original Code is HAT. The Initial Developer of the
 27  * Original Code is Bill Foote, with contributions from others
 28  * at JavaSoft/Sun.
 29  */
 30 
 31 package jdk.test.lib.hprof.model;
 32 
 33 import java.io.IOException;
 34 import java.nio.ByteOrder;
 35 import java.util.Objects;
 36 
 37 /**
 38  * An array of values, that is, an array of ints, boolean, floats, etc.
 39  * or flat array of primitive objects.
 40  *
 41  * @author      Bill Foote
 42  */
 43 public class JavaValueArray extends JavaLazyReadObject
 44                 /*imports*/ implements ArrayTypeCodes {
 45 























 46     private static int elementSize(byte type) {
 47         switch (type) {
 48             case 'B':
 49             case 'Z':
 50                 return 1;
 51             case 'C':
 52             case 'S':
 53                 return 2;
 54             case 'I':
 55             case 'F':
 56                 return 4;
 57             case 'J':
 58             case 'D':
 59                 return 8;
 60             default:
 61                 throw new RuntimeException("invalid array element type: " + type);
 62         }
 63     }
 64 
 65     /*
 66      * Java primitive array record (HPROF_GC_PRIM_ARRAY_DUMP) looks
 67      * as below:
 68      *
 69      *    object ID
 70      *    stack trace serial number (int)
 71      *    number of elements (int)
 72      *    element type (byte)
 73      *    array data
 74      */
 75     @Override
 76     protected final long readValueLength() throws IOException {
 77         long offset = getOffset() + idSize() + 4;
 78         // length of the array in elements
 79         long len = buf().getInt(offset);
 80         // byte length of array
 81         return len * elementSize(getRealElementType());
 82     }
 83 
 84     private long dataStartOffset() {
 85         return getOffset() + idSize() + 4 + 4 + 1;
 86     }
 87 
 88 
 89     @Override
 90     protected final JavaThing[] readValue() throws IOException {
 91         int len = getLength();
 92         long offset = dataStartOffset();
 93 
 94         JavaThing[] res = new JavaThing[len];
 95         synchronized (buf()) {
 96             switch (getElementType()) {
 97                 case 'Z': {
 98                               for (int i = 0; i < len; i++) {
 99                                   res[i] = new JavaBoolean(booleanAt(offset));
100                                   offset += 1;
101                               }

133                               for (int i = 0; i < len; i++) {
134                                   res[i] = new JavaLong(longAt(offset));
135                                   offset += 8;
136                               }
137                               return res;
138                 }
139                 case 'F': {
140                               for (int i = 0; i < len; i++) {
141                                   res[i] = new JavaFloat(floatAt(offset));
142                                   offset += 4;
143                               }
144                               return res;
145                 }
146                 case 'D': {
147                               for (int i = 0; i < len; i++) {
148                                   res[i] = new JavaDouble(doubleAt(offset));
149                                   offset += 8;
150                               }
151                               return res;
152                 }
153                 case 'Q': {
154                     for (int i = 0; i < len; i++) {
155                         res[i] = new InlinedJavaObject(flatArrayElementClass, offset);
156                         offset += flatArrayElementClass.getInlinedInstanceSize();
157                     }
158                     return res;
159                 }
160                 default: {
161                              throw new RuntimeException("unknown primitive type?");
162                 }
163             }
164         }
165     }
166 
167     // JavaClass set only after resolve.
168     private JavaClass clazz;
169 
170     private long objID;
171 
172     // This field contains elementSignature byte and
173     // divider to be used to calculate length. Note that
174     // length of content byte[] is not same as array length.
175     // Actual array length is (byte[].length / divider)
176     private int data;
177 
178     // First 8 bits of data is used for element signature
179     private static final int SIGNATURE_MASK = 0x0FF;
180 
181     // Next 8 bits of data is used for length divider
182     private static final int LENGTH_DIVIDER_MASK = 0x0FF00;
183 
184     // Number of bits to shift to get length divider
185     private static final int LENGTH_DIVIDER_SHIFT = 8;
186 
187     // Flat array support.
188     private JavaClass flatArrayElementClass;
189 
190     public JavaValueArray(long id, byte elementSignature, long offset) {
191         super(offset);
192         this.objID = id;
193         this.data = (elementSignature & SIGNATURE_MASK);
194     }
195 
196     public JavaClass getClazz() {
197         return clazz;
198     }
199 
200     public boolean isFlatArray() {
201         return flatArrayElementClass != null;
202     }
203 
204     public JavaClass getFlatElementClazz() {
205         return flatArrayElementClass;
206     }
207 
208     public void visitReferencedObjects(JavaHeapObjectVisitor v) {
209         super.visitReferencedObjects(v);
210     }
211 
212     public void resolve(Snapshot snapshot) {
213         if (clazz instanceof JavaClass) {
214             return;
215         }
216 
217         byte elementType = getElementType();
218         String elementSig = "" + (char)elementType;
219         // Check if this is a flat array of primitive objects.
220         Number elementClassID = snapshot.findFlatArrayElementType(objID);
221         if (elementClassID != null) {
222             // This is flat array.
223             JavaHeapObject elementClazz = snapshot.findThing(getIdValue(elementClassID));
224             if (elementClazz instanceof JavaClass elementJavaClazz) {
225                 flatArrayElementClass = elementJavaClazz;
226                 // need to resolve the element class
227                 flatArrayElementClass.resolve(snapshot);
228                 elementSig = "Q" + flatArrayElementClass.getName() + ";";
229             } else {
230                 // The class not found.
231                 System.out.println("WARNING: flat array element class not found");
232             }
233         }
234         clazz = snapshot.getArrayClass(elementSig);
235         getClazz().addInstance(this);
236         super.resolve(snapshot);
237     }
238 
239     public int getLength() {
240         int divider = (data & LENGTH_DIVIDER_MASK) >>> LENGTH_DIVIDER_SHIFT;
241         if (divider == 0) {
242             byte elementSignature = getElementType();
243             switch (elementSignature) {
244             case 'B':
245             case 'Z':
246                 divider = 1;
247                 break;
248             case 'C':
249             case 'S':
250                 divider = 2;
251                 break;
252             case 'I':
253             case 'F':
254                 divider = 4;
255                 break;
256             case 'J':
257             case 'D':
258                 divider = 8;
259                 break;
260             case 'Q':
261                 divider = flatArrayElementClass.getInlinedInstanceSize();
262                 break;
263             default:
264                 throw new RuntimeException("unknown primitive type: " +
265                                 elementSignature);
266             }
267             data |= (divider << LENGTH_DIVIDER_SHIFT);
268         }
269         return (int)(getValueLength() / divider);
270     }
271 
272     public JavaThing[] getElements() {
273         return getValue();
274     }
275 
276     public byte getElementType() {
277         return isFlatArray() ? (byte)'Q' : getRealElementType();
278     }
279 
280     private byte getRealElementType() {
281         return (byte) (data & SIGNATURE_MASK);
282     }
283 
284     private void checkIndex(int index) {
285         Objects.checkIndex(index, getLength());
286     }
287 
288     private void requireType(char type) {
289         if (getElementType() != type) {
290             throw new RuntimeException("not of type : " + type);
291         }
292     }
293 
294     public String valueString() {
295         return valueString(true);
296     }
297 
298     public String valueString(boolean bigLimit) {
299         // Char arrays deserve special treatment
300         StringBuilder result;
301         JavaThing[] things = getValue();
302         byte elementSignature = getElementType();
303         if (elementSignature == 'C' && !isFlatArray())  {
304             result = new StringBuilder();
305             for (int i = 0; i < things.length; i++) {
306                 result.append(things[i]);
307             }
308         } else {
309             int limit = 8;
310             if (bigLimit) {
311                 limit = 1000;
312             }
313             result = new StringBuilder("{");
314             for (int i = 0; i < things.length; i++) {
315                 if (i > 0) {
316                     result.append(", ");
317                 }
318                 if (i >= limit) {
319                     result.append("... ");
320                     break;
321                 }
322                 switch (elementSignature) {
323                     case 'Z': {
< prev index next >