< prev index next >

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

Print this page

 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 
 27 /*
 28  * The Original Code is HAT. The Initial Developer of the
 29  * Original Code is Bill Foote, with contributions from others
 30  * at JavaSoft/Sun.
 31  */
 32 
 33 package jdk.test.lib.hprof.model;
 34 
 35 import java.io.IOException;
 36 import java.util.Objects;
 37 
 38 /**
 39  * An array of values, that is, an array of ints, boolean, floats or the like.

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

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







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


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



202         super(offset);

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








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













222         }

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



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




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

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




343                     default: {
344                         throw new RuntimeException("unknown primitive type?");
345                     }
346                 }
347             }
348             result.append('}');
349         }
350         return result.toString();
351     }
352 }

 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 
 27 /*
 28  * The Original Code is HAT. The Initial Developer of the
 29  * Original Code is Bill Foote, with contributions from others
 30  * at JavaSoft/Sun.
 31  */
 32 
 33 package jdk.test.lib.hprof.model;
 34 
 35 import java.io.IOException;
 36 import java.util.Objects;
 37 
 38 /**
 39  * An array of values, that is, an array of ints, boolean, floats, etc.
 40  * or flat array of primitive objects.
 41  *
 42  * @author      Bill Foote
 43  */
 44 public class JavaValueArray extends JavaLazyReadObject
 45                 /*imports*/ implements ArrayTypeCodes {
 46 
 47     private static int elementSize(byte type) {
 48         switch (type) {
 49             case 'B':

 50             case 'Z':
 51                 return 1;
 52             case 'C':

 53             case 'S':
 54                 return 2;
 55             case 'I':

 56             case 'F':
 57                 return 4;
 58             case 'J':

 59             case 'D':



















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

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

343                     case 'I': {
344                         int val = ((JavaInt)things[i]).value;
345                         result.append(val);
346                         break;
347                     }
348                     case 'J': {         // long
349                         long val = ((JavaLong)things[i]).value;
350                         result.append(val);
351                         break;
352                     }
353                     case 'F': {
354                         float val = ((JavaFloat)things[i]).value;
355                         result.append(val);
356                         break;
357                     }
358                     case 'D': {         // double
359                         double val = ((JavaDouble)things[i]).value;
360                         result.append(val);
361                         break;
362                     }
363                     case 'Q': {
364                         InlinedJavaObject obj = (InlinedJavaObject)things[i];
365                         result.append(obj);
366                     }
367                     default: {
368                         throw new RuntimeException("unknown primitive type?");
369                     }
370                 }
371             }
372             result.append('}');
373         }
374         return result.toString();
375     }
376 }
< prev index next >