< prev index next >

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

Print this page

 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 /*
 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.util.Objects;
 35 
 36 /**
 37  * An array of values, that is, an array of ints, boolean, floats or the like.

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

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







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


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



200         super(offset);

201         this.data = (elementSignature & SIGNATURE_MASK);
202     }
203 
204     public JavaClass getClazz() {
205         return clazz;
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         byte elementSig = getElementType();
217         clazz = snapshot.findClass(arrayTypeName(elementSig));
218         if (clazz == null) {
219             clazz = snapshot.getArrayClass("" + ((char) elementSig));













220         }

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



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




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

321                     case 'I': {
322                         int val = ((JavaInt)things[i]).value;
323                         result.append(val);
324                         break;
325                     }
326                     case 'J': {         // long
327                         long val = ((JavaLong)things[i]).value;
328                         result.append(val);
329                         break;
330                     }
331                     case 'F': {
332                         float val = ((JavaFloat)things[i]).value;
333                         result.append(val);
334                         break;
335                     }
336                     case 'D': {         // double
337                         double val = ((JavaDouble)things[i]).value;
338                         result.append(val);
339                         break;
340                     }




341                     default: {
342                         throw new RuntimeException("unknown primitive type?");
343                     }
344                 }
345             }
346             result.append('}');
347         }
348         return result.toString();
349     }
350 
351     // Tries to represent the value as string (used by JavaObject.toString).
352     public String valueAsString() {
353         if (getElementType() == 'B')  {
354             JavaThing[] things = getValue();
355             byte[] bytes = new byte[things.length];
356             for (int i = 0; i < things.length; i++) {
357                 bytes[i] = ((JavaByte)things[i]).value;
358             }
359             return new String(bytes);
360         }

 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 /*
 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.util.Objects;
 35 
 36 /**
 37  * An array of values, that is, an array of ints, boolean, floats, etc.
 38  * or flat array of primitive objects.
 39  *
 40  * @author      Bill Foote
 41  */
 42 public class JavaValueArray extends JavaLazyReadObject
 43                 /*imports*/ implements ArrayTypeCodes {
 44 























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

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

341                     case 'I': {
342                         int val = ((JavaInt)things[i]).value;
343                         result.append(val);
344                         break;
345                     }
346                     case 'J': {         // long
347                         long val = ((JavaLong)things[i]).value;
348                         result.append(val);
349                         break;
350                     }
351                     case 'F': {
352                         float val = ((JavaFloat)things[i]).value;
353                         result.append(val);
354                         break;
355                     }
356                     case 'D': {         // double
357                         double val = ((JavaDouble)things[i]).value;
358                         result.append(val);
359                         break;
360                     }
361                     case 'Q': {
362                         InlinedJavaObject obj = (InlinedJavaObject)things[i];
363                         result.append(obj);
364                     }
365                     default: {
366                         throw new RuntimeException("unknown primitive type?");
367                     }
368                 }
369             }
370             result.append('}');
371         }
372         return result.toString();
373     }
374 
375     // Tries to represent the value as string (used by JavaObject.toString).
376     public String valueAsString() {
377         if (getElementType() == 'B')  {
378             JavaThing[] things = getValue();
379             byte[] bytes = new byte[things.length];
380             for (int i = 0; i < things.length; i++) {
381                 bytes[i] = ((JavaByte)things[i]).value;
382             }
383             return new String(bytes);
384         }
< prev index next >