--- old/test/lib/share/classes/jdk/test/lib/hprof/model/JavaObject.java 2016-08-11 12:50:38.275489400 -0400 +++ /dev/null 2016-08-11 12:50:38.000000000 -0400 @@ -1,334 +0,0 @@ -/* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - -/* - * The Original Code is HAT. The Initial Developer of the - * Original Code is Bill Foote, with contributions from others - * at JavaSoft/Sun. - */ - -package jdk.test.lib.hprof.model; - -import java.io.IOException; -import jdk.test.lib.hprof.parser.ReadBuffer; - -/** - * Represents Java instance - * - * @author Bill Foote - */ -public class JavaObject extends JavaLazyReadObject { - - private Object clazz; // Number before resolve - // JavaClass after resolve - /** - * Construct a new JavaObject. - * - * @param classID id of the class object - * @param offset The offset of field data - */ - public JavaObject(long classID, long offset) { - super(offset); - this.clazz = makeId(classID); - } - - public void resolve(Snapshot snapshot) { - if (clazz instanceof JavaClass) { - return; - } - if (clazz instanceof Number) { - long classID = getIdValue((Number)clazz); - clazz = snapshot.findThing(classID); - if (! (clazz instanceof JavaClass)) { - warn("Class " + Long.toHexString(classID) + " not found, " + - "adding fake class!"); - int length; - ReadBuffer buf = snapshot.getReadBuffer(); - int idSize = snapshot.getIdentifierSize(); - long lenOffset = getOffset() + 2*idSize + 4; - try { - length = buf.getInt(lenOffset); - } catch (IOException exp) { - throw new RuntimeException(exp); - } - clazz = snapshot.addFakeInstanceClass(classID, length); - } - } else { - throw new InternalError("should not reach here"); - } - - JavaClass cl = (JavaClass) clazz; - cl.resolve(snapshot); - - // while resolving, parse fields in verbose mode. - // but, getFields calls parseFields in non-verbose mode - // to avoid printing warnings repeatedly. - parseFields(getValue(), true); - - cl.addInstance(this); - super.resolve(snapshot); - } - - /** - * Are we the same type as other? We are iff our clazz is the - * same type as other's. - */ - public boolean isSameTypeAs(JavaThing other) { - if (!(other instanceof JavaObject)) { - return false; - } - JavaObject oo = (JavaObject) other; - return getClazz().equals(oo.getClazz()); - } - - /** - * Return our JavaClass object. This may only be called after resolve. - */ - public JavaClass getClazz() { - return (JavaClass) clazz; - } - - public JavaThing[] getFields() { - // pass false to verbose mode so that dereference - // warnings are not printed. - return parseFields(getValue(), false); - } - - // returns the value of field of given name - public JavaThing getField(String name) { - JavaThing[] flds = getFields(); - JavaField[] instFields = getClazz().getFieldsForInstance(); - for (int i = 0; i < instFields.length; i++) { - if (instFields[i].getName().equals(name)) { - return flds[i]; - } - } - return null; - } - - public int compareTo(JavaThing other) { - if (other instanceof JavaObject) { - JavaObject oo = (JavaObject) other; - return getClazz().getName().compareTo(oo.getClazz().getName()); - } - return super.compareTo(other); - } - - public void visitReferencedObjects(JavaHeapObjectVisitor v) { - super.visitReferencedObjects(v); - JavaThing[] flds = getFields(); - for (int i = 0; i < flds.length; i++) { - if (flds[i] != null) { - if (v.mightExclude() - && v.exclude(getClazz().getClassForField(i), - getClazz().getFieldForInstance(i))) - { - // skip it - } else if (flds[i] instanceof JavaHeapObject) { - v.visit((JavaHeapObject) flds[i]); - } - } - } - } - - public boolean refersOnlyWeaklyTo(Snapshot ss, JavaThing other) { - if (ss.getWeakReferenceClass() != null) { - final int referentFieldIndex = ss.getReferentFieldIndex(); - if (ss.getWeakReferenceClass().isAssignableFrom(getClazz())) { - // - // REMIND: This introduces a dependency on the JDK - // implementation that is undesirable. - JavaThing[] flds = getFields(); - for (int i = 0; i < flds.length; i++) { - if (i != referentFieldIndex && flds[i] == other) { - return false; - } - } - return true; - } - } - return false; - } - - /** - * Describe the reference that this thing has to target. This will only - * be called if target is in the array returned by getChildrenForRootset. - */ - public String describeReferenceTo(JavaThing target, Snapshot ss) { - JavaThing[] flds = getFields(); - for (int i = 0; i < flds.length; i++) { - if (flds[i] == target) { - JavaField f = getClazz().getFieldForInstance(i); - return "field " + f.getName(); - } - } - return super.describeReferenceTo(target, ss); - } - - public String toString() { - if (getClazz().isString()) { - JavaThing value = getField("value"); - if (value instanceof JavaValueArray) { - return ((JavaValueArray)value).valueString(); - } else { - return "null"; - } - } else { - return super.toString(); - } - } - - // Internals only below this point - - /* - * Java instance record (HPROF_GC_INSTANCE_DUMP) looks as below: - * - * object ID - * stack trace serial number (int) - * class ID - * data length (int) - * byte[length] - */ - protected final int readValueLength() throws IOException { - JavaClass cl = getClazz(); - int idSize = cl.getIdentifierSize(); - long lengthOffset = getOffset() + 2*idSize + 4; - return cl.getReadBuffer().getInt(lengthOffset); - } - - protected final byte[] readValue() throws IOException { - JavaClass cl = getClazz(); - int idSize = cl.getIdentifierSize(); - ReadBuffer buf = cl.getReadBuffer(); - long offset = getOffset() + 2*idSize + 4; - int length = buf.getInt(offset); - if (length == 0) { - return Snapshot.EMPTY_BYTE_ARRAY; - } else { - byte[] res = new byte[length]; - buf.get(offset + 4, res); - return res; - } - } - - private JavaThing[] parseFields(byte[] data, boolean verbose) { - JavaClass cl = getClazz(); - int target = cl.getNumFieldsForInstance(); - JavaField[] fields = cl.getFields(); - JavaThing[] fieldValues = new JavaThing[target]; - Snapshot snapshot = cl.getSnapshot(); - int idSize = snapshot.getIdentifierSize(); - int fieldNo = 0; - // In the dump file, the fields are stored in this order: - // fields of most derived class (immediate class) are stored - // first and then the super class and so on. In this object, - // fields are stored in the reverse ("natural") order. i.e., - // fields of most super class are stored first. - - // target variable is used to compensate for the fact that - // the dump file starts field values from the leaf working - // upwards in the inheritance hierarchy, whereas JavaObject - // starts with the top of the inheritance hierarchy and works down. - target -= fields.length; - JavaClass currClass = cl; - int index = 0; - for (int i = 0; i < fieldValues.length; i++, fieldNo++) { - while (fieldNo >= fields.length) { - currClass = currClass.getSuperclass(); - fields = currClass.getFields(); - fieldNo = 0; - target -= fields.length; - } - JavaField f = fields[fieldNo]; - char sig = f.getSignature().charAt(0); - switch (sig) { - case 'L': - case '[': { - long id = objectIdAt(index, data); - index += idSize; - JavaObjectRef ref = new JavaObjectRef(id); - fieldValues[target+fieldNo] = ref.dereference(snapshot, f, verbose); - break; - } - case 'Z': { - byte value = byteAt(index, data); - index++; - fieldValues[target+fieldNo] = new JavaBoolean(value != 0); - break; - } - case 'B': { - byte value = byteAt(index, data); - index++; - fieldValues[target+fieldNo] = new JavaByte(value); - break; - } - case 'S': { - short value = shortAt(index, data); - index += 2; - fieldValues[target+fieldNo] = new JavaShort(value); - break; - } - case 'C': { - char value = charAt(index, data); - index += 2; - fieldValues[target+fieldNo] = new JavaChar(value); - break; - } - case 'I': { - int value = intAt(index, data); - index += 4; - fieldValues[target+fieldNo] = new JavaInt(value); - break; - } - case 'J': { - long value = longAt(index, data); - index += 8; - fieldValues[target+fieldNo] = new JavaLong(value); - break; - } - case 'F': { - float value = floatAt(index, data); - index += 4; - fieldValues[target+fieldNo] = new JavaFloat(value); - break; - } - case 'D': { - double value = doubleAt(index, data); - index += 8; - fieldValues[target+fieldNo] = new JavaDouble(value); - break; - } - default: - throw new RuntimeException("invalid signature: " + sig); - } - } - return fieldValues; - } - - private void warn(String msg) { - System.out.println("WARNING: " + msg); - } -} --- /dev/null 2016-08-11 12:50:38.000000000 -0400 +++ new/test/lib/jdk/test/lib/hprof/model/JavaObject.java 2016-08-11 12:50:37.523959000 -0400 @@ -0,0 +1,334 @@ +/* + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * The Original Code is HAT. The Initial Developer of the + * Original Code is Bill Foote, with contributions from others + * at JavaSoft/Sun. + */ + +package jdk.test.lib.hprof.model; + +import java.io.IOException; +import jdk.test.lib.hprof.parser.ReadBuffer; + +/** + * Represents Java instance + * + * @author Bill Foote + */ +public class JavaObject extends JavaLazyReadObject { + + private Object clazz; // Number before resolve + // JavaClass after resolve + /** + * Construct a new JavaObject. + * + * @param classID id of the class object + * @param offset The offset of field data + */ + public JavaObject(long classID, long offset) { + super(offset); + this.clazz = makeId(classID); + } + + public void resolve(Snapshot snapshot) { + if (clazz instanceof JavaClass) { + return; + } + if (clazz instanceof Number) { + long classID = getIdValue((Number)clazz); + clazz = snapshot.findThing(classID); + if (! (clazz instanceof JavaClass)) { + warn("Class " + Long.toHexString(classID) + " not found, " + + "adding fake class!"); + int length; + ReadBuffer buf = snapshot.getReadBuffer(); + int idSize = snapshot.getIdentifierSize(); + long lenOffset = getOffset() + 2*idSize + 4; + try { + length = buf.getInt(lenOffset); + } catch (IOException exp) { + throw new RuntimeException(exp); + } + clazz = snapshot.addFakeInstanceClass(classID, length); + } + } else { + throw new InternalError("should not reach here"); + } + + JavaClass cl = (JavaClass) clazz; + cl.resolve(snapshot); + + // while resolving, parse fields in verbose mode. + // but, getFields calls parseFields in non-verbose mode + // to avoid printing warnings repeatedly. + parseFields(getValue(), true); + + cl.addInstance(this); + super.resolve(snapshot); + } + + /** + * Are we the same type as other? We are iff our clazz is the + * same type as other's. + */ + public boolean isSameTypeAs(JavaThing other) { + if (!(other instanceof JavaObject)) { + return false; + } + JavaObject oo = (JavaObject) other; + return getClazz().equals(oo.getClazz()); + } + + /** + * Return our JavaClass object. This may only be called after resolve. + */ + public JavaClass getClazz() { + return (JavaClass) clazz; + } + + public JavaThing[] getFields() { + // pass false to verbose mode so that dereference + // warnings are not printed. + return parseFields(getValue(), false); + } + + // returns the value of field of given name + public JavaThing getField(String name) { + JavaThing[] flds = getFields(); + JavaField[] instFields = getClazz().getFieldsForInstance(); + for (int i = 0; i < instFields.length; i++) { + if (instFields[i].getName().equals(name)) { + return flds[i]; + } + } + return null; + } + + public int compareTo(JavaThing other) { + if (other instanceof JavaObject) { + JavaObject oo = (JavaObject) other; + return getClazz().getName().compareTo(oo.getClazz().getName()); + } + return super.compareTo(other); + } + + public void visitReferencedObjects(JavaHeapObjectVisitor v) { + super.visitReferencedObjects(v); + JavaThing[] flds = getFields(); + for (int i = 0; i < flds.length; i++) { + if (flds[i] != null) { + if (v.mightExclude() + && v.exclude(getClazz().getClassForField(i), + getClazz().getFieldForInstance(i))) + { + // skip it + } else if (flds[i] instanceof JavaHeapObject) { + v.visit((JavaHeapObject) flds[i]); + } + } + } + } + + public boolean refersOnlyWeaklyTo(Snapshot ss, JavaThing other) { + if (ss.getWeakReferenceClass() != null) { + final int referentFieldIndex = ss.getReferentFieldIndex(); + if (ss.getWeakReferenceClass().isAssignableFrom(getClazz())) { + // + // REMIND: This introduces a dependency on the JDK + // implementation that is undesirable. + JavaThing[] flds = getFields(); + for (int i = 0; i < flds.length; i++) { + if (i != referentFieldIndex && flds[i] == other) { + return false; + } + } + return true; + } + } + return false; + } + + /** + * Describe the reference that this thing has to target. This will only + * be called if target is in the array returned by getChildrenForRootset. + */ + public String describeReferenceTo(JavaThing target, Snapshot ss) { + JavaThing[] flds = getFields(); + for (int i = 0; i < flds.length; i++) { + if (flds[i] == target) { + JavaField f = getClazz().getFieldForInstance(i); + return "field " + f.getName(); + } + } + return super.describeReferenceTo(target, ss); + } + + public String toString() { + if (getClazz().isString()) { + JavaThing value = getField("value"); + if (value instanceof JavaValueArray) { + return ((JavaValueArray)value).valueString(); + } else { + return "null"; + } + } else { + return super.toString(); + } + } + + // Internals only below this point + + /* + * Java instance record (HPROF_GC_INSTANCE_DUMP) looks as below: + * + * object ID + * stack trace serial number (int) + * class ID + * data length (int) + * byte[length] + */ + protected final int readValueLength() throws IOException { + JavaClass cl = getClazz(); + int idSize = cl.getIdentifierSize(); + long lengthOffset = getOffset() + 2*idSize + 4; + return cl.getReadBuffer().getInt(lengthOffset); + } + + protected final byte[] readValue() throws IOException { + JavaClass cl = getClazz(); + int idSize = cl.getIdentifierSize(); + ReadBuffer buf = cl.getReadBuffer(); + long offset = getOffset() + 2*idSize + 4; + int length = buf.getInt(offset); + if (length == 0) { + return Snapshot.EMPTY_BYTE_ARRAY; + } else { + byte[] res = new byte[length]; + buf.get(offset + 4, res); + return res; + } + } + + private JavaThing[] parseFields(byte[] data, boolean verbose) { + JavaClass cl = getClazz(); + int target = cl.getNumFieldsForInstance(); + JavaField[] fields = cl.getFields(); + JavaThing[] fieldValues = new JavaThing[target]; + Snapshot snapshot = cl.getSnapshot(); + int idSize = snapshot.getIdentifierSize(); + int fieldNo = 0; + // In the dump file, the fields are stored in this order: + // fields of most derived class (immediate class) are stored + // first and then the super class and so on. In this object, + // fields are stored in the reverse ("natural") order. i.e., + // fields of most super class are stored first. + + // target variable is used to compensate for the fact that + // the dump file starts field values from the leaf working + // upwards in the inheritance hierarchy, whereas JavaObject + // starts with the top of the inheritance hierarchy and works down. + target -= fields.length; + JavaClass currClass = cl; + int index = 0; + for (int i = 0; i < fieldValues.length; i++, fieldNo++) { + while (fieldNo >= fields.length) { + currClass = currClass.getSuperclass(); + fields = currClass.getFields(); + fieldNo = 0; + target -= fields.length; + } + JavaField f = fields[fieldNo]; + char sig = f.getSignature().charAt(0); + switch (sig) { + case 'L': + case '[': { + long id = objectIdAt(index, data); + index += idSize; + JavaObjectRef ref = new JavaObjectRef(id); + fieldValues[target+fieldNo] = ref.dereference(snapshot, f, verbose); + break; + } + case 'Z': { + byte value = byteAt(index, data); + index++; + fieldValues[target+fieldNo] = new JavaBoolean(value != 0); + break; + } + case 'B': { + byte value = byteAt(index, data); + index++; + fieldValues[target+fieldNo] = new JavaByte(value); + break; + } + case 'S': { + short value = shortAt(index, data); + index += 2; + fieldValues[target+fieldNo] = new JavaShort(value); + break; + } + case 'C': { + char value = charAt(index, data); + index += 2; + fieldValues[target+fieldNo] = new JavaChar(value); + break; + } + case 'I': { + int value = intAt(index, data); + index += 4; + fieldValues[target+fieldNo] = new JavaInt(value); + break; + } + case 'J': { + long value = longAt(index, data); + index += 8; + fieldValues[target+fieldNo] = new JavaLong(value); + break; + } + case 'F': { + float value = floatAt(index, data); + index += 4; + fieldValues[target+fieldNo] = new JavaFloat(value); + break; + } + case 'D': { + double value = doubleAt(index, data); + index += 8; + fieldValues[target+fieldNo] = new JavaDouble(value); + break; + } + default: + throw new RuntimeException("invalid signature: " + sig); + } + } + return fieldValues; + } + + private void warn(String msg) { + System.out.println("WARNING: " + msg); + } +}