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 jdk.test.lib.hprof.parser.ReadBuffer;
35
36 /**
37 * Represents Java instance
38 *
39 * @author Bill Foote
40 */
41 public class JavaObject extends JavaLazyReadObject {
42
43 private Object clazz; // Number before resolve
44 // JavaClass after resolve
45 /**
46 * Construct a new JavaObject.
47 *
48 * @param classID id of the class object
49 * @param offset The offset of field data
50 */
51 public JavaObject(long classID, long offset) {
52 super(offset);
53 this.clazz = makeId(classID);
54 }
55
56 public void resolve(Snapshot snapshot) {
57 if (clazz instanceof JavaClass) {
58 return;
59 }
60 if (clazz instanceof Number) {
61 long classID = getIdValue((Number)clazz);
62 clazz = snapshot.findThing(classID);
63 if (! (clazz instanceof JavaClass)) {
64 warn("Class " + Long.toHexString(classID) + " not found, " +
65 "adding fake class!");
66 int length;
67 ReadBuffer buf = snapshot.getReadBuffer();
68 int idSize = snapshot.getIdentifierSize();
69 long lenOffset = getOffset() + 2*idSize + 4;
70 try {
71 length = buf.getInt(lenOffset);
72 } catch (IOException exp) {
73 throw new RuntimeException(exp);
194 } else {
195 return "null";
196 }
197 } else {
198 return super.toString();
199 }
200 }
201
202 // Internals only below this point
203
204 /*
205 * Java instance record (HPROF_GC_INSTANCE_DUMP) looks as below:
206 *
207 * object ID
208 * stack trace serial number (int)
209 * class ID
210 * data length (int)
211 * byte[length]
212 */
213 @Override
214 protected final long readValueLength() throws IOException {
215 long lengthOffset = getOffset() + 2 * idSize() + 4;
216 return buf().getInt(lengthOffset);
217 }
218
219 @Override
220 protected final JavaThing[] readValue() throws IOException {
221 return parseFields(false);
222 }
223
224 private long dataStartOffset() {
225 return getOffset() + idSize() + 4 + idSize() + 4;
226 }
227
228 private JavaThing[] parseFields(boolean verbose) {
229 JavaClass cl = getClazz();
230 int target = cl.getNumFieldsForInstance();
231 JavaField[] fields = cl.getFields();
232 JavaThing[] fieldValues = new JavaThing[target];
233 Snapshot snapshot = cl.getSnapshot();
234 int fieldNo = 0;
235 // In the dump file, the fields are stored in this order:
236 // fields of most derived class (immediate class) are stored
237 // first and then the super class and so on. In this object,
238 // fields are stored in the reverse ("natural") order. i.e.,
239 // fields of most super class are stored first.
240
241 // target variable is used to compensate for the fact that
242 // the dump file starts field values from the leaf working
243 // upwards in the inheritance hierarchy, whereas JavaObject
244 // starts with the top of the inheritance hierarchy and works down.
245 target -= fields.length;
246 JavaClass currClass = cl;
247 long offset = dataStartOffset();
248 for (int i = 0; i < fieldValues.length; i++, fieldNo++) {
249 while (fieldNo >= fields.length) {
250 currClass = currClass.getSuperclass();
251 fields = currClass.getFields();
252 fieldNo = 0;
253 target -= fields.length;
254 }
255 JavaField f = fields[fieldNo];
256 char sig = f.getSignature().charAt(0);
257 try {
258 switch (sig) {
259 case 'L':
260 case '[': {
261 long id = objectIdAt(offset);
262 offset += idSize();
263 JavaObjectRef ref = new JavaObjectRef(id);
264 fieldValues[target+fieldNo] = ref.dereference(snapshot, f, verbose);
265 break;
266 }
267 case 'Z': {
268 byte value = byteAt(offset);
269 offset++;
270 fieldValues[target+fieldNo] = new JavaBoolean(value != 0);
271 break;
272 }
273 case 'B': {
274 byte value = byteAt(offset);
275 offset++;
276 fieldValues[target+fieldNo] = new JavaByte(value);
277 break;
278 }
279 case 'S': {
280 short value = shortAt(offset);
281 offset += 2;
282 fieldValues[target+fieldNo] = new JavaShort(value);
283 break;
284 }
285 case 'C': {
286 char value = charAt(offset);
287 offset += 2;
288 fieldValues[target+fieldNo] = new JavaChar(value);
289 break;
290 }
291 case 'I': {
292 int value = intAt(offset);
293 offset += 4;
294 fieldValues[target+fieldNo] = new JavaInt(value);
295 break;
296 }
297 case 'J': {
298 long value = longAt(offset);
299 offset += 8;
300 fieldValues[target+fieldNo] = new JavaLong(value);
301 break;
302 }
303 case 'F': {
304 float value = floatAt(offset);
305 offset += 4;
306 fieldValues[target+fieldNo] = new JavaFloat(value);
307 break;
308 }
309 case 'D': {
310 double value = doubleAt(offset);
311 offset += 8;
312 fieldValues[target+fieldNo] = new JavaDouble(value);
313 break;
314 }
315 default:
316 throw new RuntimeException("invalid signature: " + sig);
317
318 }
319 } catch (IOException exp) {
320 System.err.println("lazy read failed at offset " + offset);
321 exp.printStackTrace();
322 return Snapshot.EMPTY_JAVATHING_ARRAY;
323 }
324 }
325 return fieldValues;
326 }
327
328 private void warn(String msg) {
329 System.out.println("WARNING: " + msg);
330 }
331 }
|
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 jdk.test.lib.hprof.parser.ReadBuffer;
35
36 /**
37 * Represents Java instance
38 *
39 * @author Bill Foote
40 */
41 public class JavaObject extends JavaLazyReadObject {
42
43 private Object clazz; // Number before resolve
44 // JavaClass after resolve
45
46 public JavaObject(Object clazz, long offset) {
47 super(offset);
48 this.clazz = clazz;
49 }
50
51 /**
52 * Construct a new JavaObject.
53 *
54 * @param classID id of the class object
55 * @param offset The offset of field data
56 */
57 public JavaObject(long classID, long offset) {
58 this(makeId(classID), offset);
59 }
60
61 public void resolve(Snapshot snapshot) {
62 if (clazz instanceof JavaClass) {
63 return;
64 }
65 if (clazz instanceof Number) {
66 long classID = getIdValue((Number)clazz);
67 clazz = snapshot.findThing(classID);
68 if (! (clazz instanceof JavaClass)) {
69 warn("Class " + Long.toHexString(classID) + " not found, " +
70 "adding fake class!");
71 int length;
72 ReadBuffer buf = snapshot.getReadBuffer();
73 int idSize = snapshot.getIdentifierSize();
74 long lenOffset = getOffset() + 2*idSize + 4;
75 try {
76 length = buf.getInt(lenOffset);
77 } catch (IOException exp) {
78 throw new RuntimeException(exp);
199 } else {
200 return "null";
201 }
202 } else {
203 return super.toString();
204 }
205 }
206
207 // Internals only below this point
208
209 /*
210 * Java instance record (HPROF_GC_INSTANCE_DUMP) looks as below:
211 *
212 * object ID
213 * stack trace serial number (int)
214 * class ID
215 * data length (int)
216 * byte[length]
217 */
218 @Override
219 protected long readValueLength() throws IOException {
220 long lengthOffset = getOffset() + 2 * idSize() + 4;
221 return buf().getInt(lengthOffset);
222 }
223
224 @Override
225 protected final JavaThing[] readValue() throws IOException {
226 return parseFields(false);
227 }
228
229 protected long dataStartOffset() {
230 return getOffset() + idSize() + 4 + idSize() + 4;
231 }
232
233 private JavaThing[] parseFields(boolean verbose) {
234 JavaClass cl = getClazz();
235 int target = cl.getNumFieldsForInstance();
236 JavaField[] fields = cl.getFields();
237 JavaThing[] fieldValues = new JavaThing[target];
238 Snapshot snapshot = cl.getSnapshot();
239 int fieldNo = 0;
240 // In the dump file, the fields are stored in this order:
241 // fields of most derived class (immediate class) are stored
242 // first and then the super class and so on. In this object,
243 // fields are stored in the reverse ("natural") order. i.e.,
244 // fields of most super class are stored first.
245
246 // target variable is used to compensate for the fact that
247 // the dump file starts field values from the leaf working
248 // upwards in the inheritance hierarchy, whereas JavaObject
249 // starts with the top of the inheritance hierarchy and works down.
250 target -= fields.length;
251 JavaClass currClass = cl;
252 long offset = dataStartOffset();
253 for (int i = 0; i < fieldValues.length; i++, fieldNo++) {
254 while (fieldNo >= fields.length) {
255 currClass = currClass.getSuperclass();
256 fields = currClass.getFields();
257 fieldNo = 0;
258 target -= fields.length;
259 }
260 JavaField f = fields[fieldNo];
261 char sig = f.getSignature().charAt(0);
262 try {
263 if (f instanceof InlinedJavaField inlinedField) {
264 JavaClass fieldClass = inlinedField.getInlinedFieldClass();
265 fieldValues[target+fieldNo] = new InlinedJavaObject(fieldClass, offset);
266 offset += fieldClass.getInlinedInstanceSize();
267 } else {
268 switch (sig) {
269 case 'Q': {
270 warn("(parseFields) field " + getClazz().getName() + "." + f.getName()
271 + " is not inlined, but has Q-signature: " + f.getSignature());
272 } // continue as 'L' object
273 case 'L':
274 case '[': {
275 long id = objectIdAt(offset);
276 offset += idSize();
277 JavaObjectRef ref = new JavaObjectRef(id);
278 fieldValues[target + fieldNo] = ref.dereference(snapshot, f, verbose);
279 break;
280 }
281 case 'Z': {
282 byte value = byteAt(offset);
283 offset++;
284 fieldValues[target + fieldNo] = new JavaBoolean(value != 0);
285 break;
286 }
287 case 'B': {
288 byte value = byteAt(offset);
289 offset++;
290 fieldValues[target + fieldNo] = new JavaByte(value);
291 break;
292 }
293 case 'S': {
294 short value = shortAt(offset);
295 offset += 2;
296 fieldValues[target + fieldNo] = new JavaShort(value);
297 break;
298 }
299 case 'C': {
300 char value = charAt(offset);
301 offset += 2;
302 fieldValues[target + fieldNo] = new JavaChar(value);
303 break;
304 }
305 case 'I': {
306 int value = intAt(offset);
307 offset += 4;
308 fieldValues[target + fieldNo] = new JavaInt(value);
309 break;
310 }
311 case 'J': {
312 long value = longAt(offset);
313 offset += 8;
314 fieldValues[target + fieldNo] = new JavaLong(value);
315 break;
316 }
317 case 'F': {
318 float value = floatAt(offset);
319 offset += 4;
320 fieldValues[target + fieldNo] = new JavaFloat(value);
321 break;
322 }
323 case 'D': {
324 double value = doubleAt(offset);
325 offset += 8;
326 fieldValues[target + fieldNo] = new JavaDouble(value);
327 break;
328 }
329 default:
330 throw new RuntimeException("invalid signature: " + sig);
331
332 }
333 }
334 } catch (IOException exp) {
335 System.err.println("lazy read failed at offset " + offset);
336 exp.printStackTrace();
337 return Snapshot.EMPTY_JAVATHING_ARRAY;
338 }
339 }
340 return fieldValues;
341 }
342
343 private void warn(String msg) {
344 System.out.println("WARNING: " + msg);
345 }
346 }
|