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 }
|