< prev index next >

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

Print this page

  1 /*
  2  * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 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

 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 jdk.test.lib.hprof.parser.ReadBuffer;
 37 
 38 /**
 39  * Represents Java instance
 40  *
 41  * @author      Bill Foote
 42  */
 43 public class JavaObject extends JavaLazyReadObject {
 44 
 45     private Object clazz;       // Number before resolve
 46                                 // JavaClass after resolve






 47     /**
 48      * Construct a new JavaObject.
 49      *
 50      * @param classID id of the class object
 51      * @param offset The offset of field data
 52      */
 53     public JavaObject(long classID, long offset) {
 54         super(offset);
 55         this.clazz = makeId(classID);
 56     }
 57 
 58     public void resolve(Snapshot snapshot) {
 59         if (clazz instanceof JavaClass) {
 60             return;
 61         }
 62         if (clazz instanceof Number) {
 63             long classID = getIdValue((Number)clazz);
 64             clazz = snapshot.findThing(classID);
 65             if (! (clazz instanceof JavaClass)) {
 66                 warn("Class " + Long.toHexString(classID) + " not found, " +
 67                      "adding fake class!");
 68                 int length;
 69                 ReadBuffer buf = snapshot.getReadBuffer();
 70                 int idSize = snapshot.getIdentifierSize();
 71                 long lenOffset = getOffset() + 2*idSize + 4;
 72                 try {
 73                     length = buf.getInt(lenOffset);
 74                 } catch (IOException exp) {
 75                     throw new RuntimeException(exp);

196             } else {
197                 return "null";
198             }
199         } else {
200             return super.toString();
201         }
202     }
203 
204     // Internals only below this point
205 
206     /*
207      * Java instance record (HPROF_GC_INSTANCE_DUMP) looks as below:
208      *
209      *     object ID
210      *     stack trace serial number (int)
211      *     class ID
212      *     data length (int)
213      *     byte[length]
214      */
215     @Override
216     protected final long readValueLength() throws IOException {
217         long lengthOffset = getOffset() + 2 * idSize() + 4;
218         return buf().getInt(lengthOffset);
219     }
220 
221     @Override
222     protected final JavaThing[] readValue() throws IOException {
223         return parseFields(false);
224     }
225 
226     private long dataStartOffset() {
227         return getOffset() + idSize() + 4 + idSize() + 4;
228     }
229 
230     private JavaThing[] parseFields(boolean verbose) {
231         JavaClass cl = getClazz();
232         int target = cl.getNumFieldsForInstance();
233         JavaField[] fields = cl.getFields();
234         JavaThing[] fieldValues = new JavaThing[target];
235         Snapshot snapshot = cl.getSnapshot();
236         int fieldNo = 0;
237         // In the dump file, the fields are stored in this order:
238         // fields of most derived class (immediate class) are stored
239         // first and then the super class and so on. In this object,
240         // fields are stored in the reverse ("natural") order. i.e.,
241         // fields of most super class are stored first.
242 
243         // target variable is used to compensate for the fact that
244         // the dump file starts field values from the leaf working
245         // upwards in the inheritance hierarchy, whereas JavaObject
246         // starts with the top of the inheritance hierarchy and works down.
247         target -= fields.length;
248         JavaClass currClass = cl;
249         long offset = dataStartOffset();
250         for (int i = 0; i < fieldValues.length; i++, fieldNo++) {
251             while (fieldNo >= fields.length) {
252                 currClass = currClass.getSuperclass();
253                 fields = currClass.getFields();
254                 fieldNo = 0;
255                 target -= fields.length;
256             }
257             JavaField f = fields[fieldNo];
258             char sig = f.getSignature().charAt(0);
259             try {
260                 switch (sig) {
261                     case 'L':
262                     case '[': {
263                         long id = objectIdAt(offset);
264                         offset += idSize();
265                         JavaObjectRef ref = new JavaObjectRef(id);
266                         fieldValues[target+fieldNo] = ref.dereference(snapshot, f, verbose);
267                         break;
268                     }
269                     case 'Z': {
270                         byte value = byteAt(offset);
271                         offset++;
272                         fieldValues[target+fieldNo] = new JavaBoolean(value != 0);
273                         break;
274                     }
275                     case 'B': {
276                         byte value = byteAt(offset);
277                         offset++;
278                         fieldValues[target+fieldNo] = new JavaByte(value);
279                         break;
280                     }
281                     case 'S': {
282                         short value = shortAt(offset);
283                         offset += 2;
284                         fieldValues[target+fieldNo] = new JavaShort(value);
285                         break;
286                     }
287                     case 'C': {
288                         char value = charAt(offset);
289                         offset += 2;
290                         fieldValues[target+fieldNo] = new JavaChar(value);
291                         break;
292                     }
293                     case 'I': {
294                         int value = intAt(offset);
295                         offset += 4;
296                         fieldValues[target+fieldNo] = new JavaInt(value);
297                         break;
298                     }
299                     case 'J': {
300                         long value = longAt(offset);
301                         offset += 8;
302                         fieldValues[target+fieldNo] = new JavaLong(value);
303                         break;
304                     }
305                     case 'F': {
306                         float value = floatAt(offset);
307                         offset += 4;
308                         fieldValues[target+fieldNo] = new JavaFloat(value);
309                         break;
310                     }
311                     case 'D': {
312                         double value = doubleAt(offset);
313                         offset += 8;
314                         fieldValues[target+fieldNo] = new JavaDouble(value);
315                         break;
316                     }
317                     default:
318                         throw new RuntimeException("invalid signature: " + sig);









319 

320                 }
321         } catch (IOException exp) {
322             System.err.println("lazy read failed at offset " + offset);
323             exp.printStackTrace();
324             return Snapshot.EMPTY_JAVATHING_ARRAY;
325             }
326         }
327         return fieldValues;
328     }
329 
330     private void warn(String msg) {
331         System.out.println("WARNING: " + msg);
332     }
333 }

  1 /*
  2  * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 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

 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 jdk.test.lib.hprof.parser.ReadBuffer;
 37 
 38 /**
 39  * Represents Java instance
 40  *
 41  * @author      Bill Foote
 42  */
 43 public class JavaObject extends JavaLazyReadObject {
 44 
 45     private Object clazz;       // Number before resolve
 46                                 // JavaClass after resolve
 47 
 48     public JavaObject(Object clazz, long offset) {
 49         super(offset);
 50         this.clazz = clazz;
 51     }
 52 
 53     /**
 54      * Construct a new JavaObject.
 55      *
 56      * @param classID id of the class object
 57      * @param offset The offset of field data
 58      */
 59     public JavaObject(long classID, long offset) {
 60         this(makeId(classID), offset);

 61     }
 62 
 63     public void resolve(Snapshot snapshot) {
 64         if (clazz instanceof JavaClass) {
 65             return;
 66         }
 67         if (clazz instanceof Number) {
 68             long classID = getIdValue((Number)clazz);
 69             clazz = snapshot.findThing(classID);
 70             if (! (clazz instanceof JavaClass)) {
 71                 warn("Class " + Long.toHexString(classID) + " not found, " +
 72                      "adding fake class!");
 73                 int length;
 74                 ReadBuffer buf = snapshot.getReadBuffer();
 75                 int idSize = snapshot.getIdentifierSize();
 76                 long lenOffset = getOffset() + 2*idSize + 4;
 77                 try {
 78                     length = buf.getInt(lenOffset);
 79                 } catch (IOException exp) {
 80                     throw new RuntimeException(exp);

201             } else {
202                 return "null";
203             }
204         } else {
205             return super.toString();
206         }
207     }
208 
209     // Internals only below this point
210 
211     /*
212      * Java instance record (HPROF_GC_INSTANCE_DUMP) looks as below:
213      *
214      *     object ID
215      *     stack trace serial number (int)
216      *     class ID
217      *     data length (int)
218      *     byte[length]
219      */
220     @Override
221     protected long readValueLength() throws IOException {
222         long lengthOffset = getOffset() + 2 * idSize() + 4;
223         return buf().getInt(lengthOffset);
224     }
225 
226     @Override
227     protected final JavaThing[] readValue() throws IOException {
228         return parseFields(false);
229     }
230 
231     protected long dataStartOffset() {
232         return getOffset() + idSize() + 4 + idSize() + 4;
233     }
234 
235     private JavaThing[] parseFields(boolean verbose) {
236         JavaClass cl = getClazz();
237         int target = cl.getNumFieldsForInstance();
238         JavaField[] fields = cl.getFields();
239         JavaThing[] fieldValues = new JavaThing[target];
240         Snapshot snapshot = cl.getSnapshot();
241         int fieldNo = 0;
242         // In the dump file, the fields are stored in this order:
243         // fields of most derived class (immediate class) are stored
244         // first and then the super class and so on. In this object,
245         // fields are stored in the reverse ("natural") order. i.e.,
246         // fields of most super class are stored first.
247 
248         // target variable is used to compensate for the fact that
249         // the dump file starts field values from the leaf working
250         // upwards in the inheritance hierarchy, whereas JavaObject
251         // starts with the top of the inheritance hierarchy and works down.
252         target -= fields.length;
253         JavaClass currClass = cl;
254         long offset = dataStartOffset();
255         for (int i = 0; i < fieldValues.length; i++, fieldNo++) {
256             while (fieldNo >= fields.length) {
257                 currClass = currClass.getSuperclass();
258                 fields = currClass.getFields();
259                 fieldNo = 0;
260                 target -= fields.length;
261             }
262             JavaField f = fields[fieldNo];
263             char sig = f.getSignature().charAt(0);
264             try {
265                 if (f instanceof InlinedJavaField inlinedField) {
266                     JavaClass fieldClass = inlinedField.getInlinedFieldClass();
267                     fieldValues[target+fieldNo] = new InlinedJavaObject(fieldClass, offset);
268                     offset += fieldClass.getInlinedInstanceSize();
269                 } else {
270                     switch (sig) {
271                         case 'Q': {
272                             warn("(parseFields) field " + getClazz().getName() + "." + f.getName()
273                                     + " is not inlined, but has Q-signature: " + f.getSignature());
274                         } // continue as 'L' object
275                         case 'L':
276                         case '[': {
277                             long id = objectIdAt(offset);
278                             offset += idSize();
279                             JavaObjectRef ref = new JavaObjectRef(id);
280                             fieldValues[target + fieldNo] = ref.dereference(snapshot, f, verbose);
281                             break;
282                         }
283                         case 'Z': {
284                             byte value = byteAt(offset);
285                             offset++;
286                             fieldValues[target + fieldNo] = new JavaBoolean(value != 0);
287                             break;
288                         }
289                         case 'B': {
290                             byte value = byteAt(offset);
291                             offset++;
292                             fieldValues[target + fieldNo] = new JavaByte(value);
293                             break;
294                         }
295                         case 'S': {
296                             short value = shortAt(offset);
297                             offset += 2;
298                             fieldValues[target + fieldNo] = new JavaShort(value);
299                             break;
300                         }
301                         case 'C': {
302                             char value = charAt(offset);
303                             offset += 2;
304                             fieldValues[target + fieldNo] = new JavaChar(value);
305                             break;
306                         }
307                         case 'I': {
308                             int value = intAt(offset);
309                             offset += 4;
310                             fieldValues[target + fieldNo] = new JavaInt(value);
311                             break;
312                         }
313                         case 'J': {
314                             long value = longAt(offset);
315                             offset += 8;
316                             fieldValues[target + fieldNo] = new JavaLong(value);
317                             break;
318                         }
319                         case 'F': {
320                             float value = floatAt(offset);
321                             offset += 4;
322                             fieldValues[target + fieldNo] = new JavaFloat(value);
323                             break;
324                         }
325                         case 'D': {
326                             double value = doubleAt(offset);
327                             offset += 8;
328                             fieldValues[target + fieldNo] = new JavaDouble(value);
329                             break;
330                         }
331                         default:
332                             throw new RuntimeException("invalid signature: " + sig);
333 
334                     }
335                 }
336             } catch (IOException exp) {
337                 System.err.println("lazy read failed at offset " + offset);
338                 exp.printStackTrace();
339                 return Snapshot.EMPTY_JAVATHING_ARRAY;
340             }
341         }
342         return fieldValues;
343     }
344 
345     private void warn(String msg) {
346         System.out.println("WARNING: " + msg);
347     }
348 }
< prev index next >