Search in sources :

Example 1 with PortableHeapDumpListener

use of com.ibm.dtfj.phd.parser.PortableHeapDumpListener in project openj9 by eclipse.

the class PHDJavaRuntime method findLoaders.

/**
 * Helper method to try to allocate classes to the correct class loader
 * There isn't an explicit mention of the loader, but an outbound reference might be to the loader.
 * First find all the objects which are class loaders.
 * The look at each file, see if it has a reference to a loader object and if so allocate it to
 * that loader.
 * @param file
 * @throws IOException
 */
private void findLoaders(HeapdumpReader newreader) throws IOException {
    // Where all the classes orginally have been put
    final PHDJavaClassLoader boot = loaders.get(null);
    // Might fail to find a class with a very corrupt dump
    final JavaClass jlc = findClass("java/lang/Class");
    final long jlcAddress = jlc == null || jlc.getID() == null ? 0 : jlc.getID().getAddress();
    // Find all the class loader classes
    final JavaClass jcl = findClass("java/lang/ClassLoader");
    final HashMap<Long, JavaClass> classLoaderClasses = new HashMap<Long, JavaClass>();
    for (Iterator<JavaClass> it = boot.getDefinedClasses(); it.hasNext(); ) {
        JavaClass cls = it.next();
        if (cls instanceof CorruptData)
            continue;
        try {
            // Avoid bug with superclass loops by remembering superclasses
            // PHD Version 4 bug - bad superclass: J2RE 5.0 IBM J9 2.3 AIX ppc64-64 build 20080314_17962_BHdSMr
            HashSet<JavaClass> supers = new HashSet<JavaClass>();
            for (JavaClass j1 = cls; j1 != null && supers.add(j1); j1 = j1.getSuperclass()) {
                /* 
					 * See if either a superclass is java.lang.ClassLoader
					 * or if no superclass information is available (old Java 5)
					 * whether the name ends with "ClassLoader"
					 */
                if (j1.equals(jcl) || cls.getSuperclass() == null && !j1.isArray() && j1.getName().endsWith("ClassLoader")) {
                    ImagePointer ip = cls.getID();
                    if (ip != null) {
                        classLoaderClasses.put(ip.getAddress(), cls);
                    }
                }
            }
        } catch (CorruptDataException e) {
        // Ignore
        }
    }
    // Number of class objects not found at class addresses
    final int[] onHeapClasses = new int[1];
    // Find all the objects which are class loaders
    final PHDJavaHeap heap = heaps.get(0);
    final HashMap<Long, JavaObject> classObjects = new HashMap<Long, JavaObject>();
    // HeapdumpReader newreader = new HeapdumpReader(file, parentImage);
    final int adjustLen = newreader.version() == 4 && newreader.isJ9() ? 1 : 0;
    try {
        newreader.parse(new PortableHeapDumpListener() {

            public void classDump(long address, long superAddress, String name, int size, int flags, int hashCode, LongEnumeration refs) throws Exception {
            }

            public void objectArrayDump(long address, long classAddress, int flags, int hashCode, LongEnumeration refs, int length, long instanceSize) throws Exception {
                if (extraObjectsCache.containsKey(address)) {
                    // Don't bother saving reference information - we can get it later
                    JavaObject jo = new PHDJavaObject.Builder(heap, address, arrayOf(classAddress, refs, adjustLen), flags, hashCode).length(length - adjustLen).instanceSize(instanceSize).build();
                    extraObjectsCache.put(address, jo);
                }
            }

            public void objectDump(long address, long classAddress, int flags, int hashCode, LongEnumeration refs, long instanceSize) throws Exception {
                JavaClass cls = classLoaderClasses.get(classAddress);
                JavaObject jo;
                if (cls != null) {
                    // Object of type java.lang.ClassLoader, so create the object and the class loader
                    jo = new PHDJavaObject.Builder(heap, address, cls, flags, hashCode).refs(refs, 0).length(PHDJavaObject.SIMPLE_OBJECT).instanceSize(instanceSize).build();
                    PHDJavaClassLoader load = new PHDJavaClassLoader(jo);
                    loaders.put(jo, load);
                } else if (classAddress == jlcAddress) {
                    if (boot.findClass(address) == null) {
                        ++onHeapClasses[0];
                    }
                    jo = new PHDJavaObject.Builder(heap, address, jlc, flags, hashCode).refs(refs, 0).length(PHDJavaObject.SIMPLE_OBJECT).instanceSize(instanceSize).build();
                    classObjects.put(address, jo);
                } else {
                    jo = null;
                }
                if (extraObjectsCache.containsKey(address)) {
                    if (jo == null) {
                        jo = new PHDJavaObject.Builder(heap, address, findClass(classAddress), flags, hashCode).refs(refs, 0).length(PHDJavaObject.SIMPLE_OBJECT).build();
                    }
                    extraObjectsCache.put(address, jo);
                }
            }

            public void primitiveArrayDump(long address, int type, int length, int flags, int hashCode, long instanceSize) throws Exception {
                if (extraObjectsCache.containsKey(address)) {
                    // Create a full object as we have the data
                    JavaObject jo = new PHDJavaObject.Builder(heap, address, findArrayOfType(type), flags, hashCode).refsAsArray(NOREFS, 0).length(length).instanceSize(instanceSize).build();
                    extraObjectsCache.put(address, jo);
                }
            }
        });
    } catch (Exception e) {
    // Ignore the exception - we will have seen it elsewhere
    // e.printStackTrace();
    } finally {
        newreader.close();
        newreader = null;
    }
    // Assign classes to the correct loaders
    // Also try to set up on/off-heap class addresses
    PHDJavaClassLoader boot2 = null;
    int foundLoader = 0;
    int notFoundLoader = 0;
    // How many java/lang classes the possible boot loader has loaded
    int loaderJavaLangCount = 0;
    boolean useFirstObjectRefAsLoader = onHeapClasses[0] == 0;
    for (Iterator<JavaClass> it = boot.getDefinedClasses(); it.hasNext(); ) {
        JavaClass j1 = it.next();
        PHDJavaClassLoader bestLoader = null;
        for (Iterator<JavaReference> it2 = j1.getReferences(); it2.hasNext(); ) {
            JavaReference jr = it2.next();
            try {
                // Is the first outbound object reference to a class loader?
                if (jr.isObjectReference()) {
                    JavaObject jo = (JavaObject) jr.getTarget();
                    PHDJavaClassLoader newLoader = loaders.get(jo);
                    if (newLoader != null) {
                        if (bestLoader == null || !useFirstObjectRefAsLoader) {
                            bestLoader = newLoader;
                        }
                    } else if (onHeapClasses[0] > 0) {
                        long addr = jo.getID().getAddress();
                        JavaObject jo2 = classObjects.get(addr);
                        if (jo2 != null) {
                            // For Java 6 jdmpview PHD files the on-heap class object is the last ref
                            // retrieve the full JavaObject from walking the heap earlier
                            ((PHDJavaClass) j1).setJavaObject(jo2);
                        }
                    }
                    // unless using off-heap classes when it is the last reference.
                    if (!j1.isArray() && useFirstObjectRefAsLoader && onHeapClasses[0] == 0)
                        break;
                }
            } catch (CorruptDataException e) {
            // e.printStackTrace();
            } catch (DataUnavailable e) {
            // e.printStackTrace();
            }
        }
        if (bestLoader != null) {
            ++foundLoader;
            // Don't remove the classes from the original loader, nor change the loader
            // as otherwise finding the array type fails
            bestLoader.prepareToMove(boot, j1);
            // Is the class by any chance the type of the class loader?
            try {
                if (boot2 == null && (j1.equals(jlc) || j1.equals(bestLoader.getObject().getJavaClass()))) {
                    // We have found the new bootstrap class loader
                    // Beware java 1.4.2 com/ibm/rmi/util/ClassInfo$NULL_CL_CLASS passes this test!
                    boot2 = bestLoader;
                }
                if (boot2 == bestLoader && j1.getName().startsWith("java/lang/"))
                    ++loaderJavaLangCount;
            } catch (CorruptDataException e) {
            }
        } else {
            ++notFoundLoader;
        }
        // Try retrieving the full JavaObject for the JavaClass
        try {
            JavaObject jo = j1.getObject();
            if (jo != null) {
                long addr = jo.getID().getAddress();
                JavaObject jo2 = classObjects.get(addr);
                if (jo2 != null) {
                    ((PHDJavaClass) j1).setJavaObject(jo2);
                }
            }
        } catch (CorruptDataException e) {
        }
    }
    // Ignore a bootstrap loader which hasn't loaded 5 java/lang classes
    if (loaderJavaLangCount < 5)
        boot2 = null;
    // Haven't found any loaders, but have a javacore file with loader information
    if (metaJavaRuntime != null) {
        for (Iterator i = metaJavaRuntime.getJavaClassLoaders(); i.hasNext(); ) {
            Object next = i.next();
            if (next instanceof CorruptData)
                continue;
            JavaClassLoader jcl2 = (JavaClassLoader) next;
            try {
                JavaObject lo = jcl2.getObject();
                if (lo != null) {
                    ImagePointer addr = lo.getID();
                    if (addr != null) {
                        ImagePointer ip = space.getPointer(addr.getAddress());
                        JavaObject jo = getObjectAtAddress(ip);
                        PHDJavaClassLoader newLoader = loaders.get(jo);
                        JavaClass loaderClass;
                        if (newLoader == null) {
                            try {
                                // Should be safe to find the class of 'jo' without rereading the PHD file
                                // as at least a dummy object should be in the extra objects cache.
                                // It could be that the object is still a dummy one with no proper class.
                                loaderClass = jo.getJavaClass();
                            } catch (CorruptDataException e) {
                                loaderClass = null;
                            }
                            JavaClass javacoreLoaderClass;
                            try {
                                javacoreLoaderClass = lo.getJavaClass();
                            } catch (CorruptDataException e) {
                                javacoreLoaderClass = null;
                            }
                            // Mismatch occurs with J2RE 5.0 IBM J9 2.3 Linux amd64-64 build j9vmxa6423-20091104
                            if (loaderClass != null && javacoreLoaderClass != null && (loaderClass.isArray() || loaderClass.getID() != null && javacoreLoaderClass.getID() != null && loaderClass.getID().getAddress() != javacoreLoaderClass.getID().getAddress())) {
                            // System.out.println("Skipping loader "+newLoader+" "+jo+" "+jo.getJavaClass()+" "+lo+" "+lo.getJavaClass()+" "+Long.toHexString(addr.getAddress())+" "+ip);
                            } else {
                                // The object should have been listed in the extra objects, so may now be the proper object
                                newLoader = new PHDJavaClassLoader(jo);
                                loaders.put(jo, newLoader);
                            }
                        } else {
                            // Replace with the offical object
                            jo = newLoader.getObject();
                            loaderClass = jo.getJavaClass();
                        }
                        if (newLoader != null) {
                            for (Iterator i2 = jcl2.getDefinedClasses(); i2.hasNext(); ) {
                                Object next2 = i2.next();
                                if (next2 instanceof CorruptData)
                                    continue;
                                JavaClass jc2 = (JavaClass) next2;
                                ImagePointer ip2 = jc2.getID();
                                JavaClass j1;
                                if (ip2 != null) {
                                    long claddr = ip2.getAddress();
                                    j1 = boot.findClass(claddr);
                                    // Not found by address, so try by name.
                                    if (j1 == null) {
                                        // But only if it is the only class of that name
                                        j1 = boot.findClassUnique(jc2.getName());
                                    } else {
                                        // Found by address
                                        try {
                                            j1.getName();
                                        } catch (CorruptDataException e) {
                                            // Our class doesn't have a name, so perhaps the javacore has the name
                                            try {
                                                String actualName = jc2.getName();
                                                PHDJavaClass pj1 = (PHDJavaClass) j1;
                                                // We will need to reindex the classloader as the name as changed
                                                pj1.setName(actualName);
                                            } catch (CorruptDataException e2) {
                                            }
                                        }
                                    }
                                } else {
                                    // But only if it is the only class of that name
                                    j1 = boot.findClassUnique(jc2.getName());
                                }
                                if (j1 != null) {
                                    newLoader.prepareToMove(boot, j1);
                                    // listed in javacore causes problems as byte etc. aren't listed
                                    if (j1.equals(loaderClass) || j1.equals(jlc)) {
                                        // We have found the new bootstrap class loader
                                        boot2 = newLoader;
                                    }
                                    for (Iterator i3 = jc2.getDeclaredMethods(); i3.hasNext(); ) {
                                        Object next3 = i3.next();
                                        if (next3 instanceof CorruptData)
                                            continue;
                                        JavaMethod jm = (JavaMethod) next3;
                                        PHDJavaClass pj1 = (PHDJavaClass) j1;
                                        pj1.addMethod(new PHDJavaMethod(space, pj1, jm));
                                    }
                                }
                            }
                        }
                    }
                }
            } catch (CorruptDataException e) {
            } catch (DataUnavailable e) {
            } catch (MemoryAccessException e) {
            }
        }
    }
    // Move the classes to the correct class loaders
    for (Iterator<JavaClass> it = boot.getDefinedClasses(); it.hasNext(); ) {
        JavaClass j1 = it.next();
        try {
            JavaClassLoader jcl2 = j1.getClassLoader();
            if (!boot.equals(jcl2) && jcl2 instanceof PHDJavaClassLoader) {
                transferClass(boot, (PHDJavaClassLoader) jcl2, j1);
            }
        } catch (CorruptDataException e) {
        }
    }
    // Reindex the loaders to account for the removed classes
    for (PHDJavaClassLoader loader : loaders.values()) {
        loader.initCache();
    }
    if (boot2 != null) {
        // Move remaining classes to new boot loader
        for (Iterator<JavaClass> it = boot.getDefinedClasses(); it.hasNext(); ) {
            JavaClass j1 = it.next();
            boot2.prepareToMove(boot, j1);
            transferClass(boot, boot2, j1);
        }
        // index the new boot loader to account for the added files
        boot2.initCache();
        // Remove the original boot class loader as it has no classes
        loaders.remove(null);
    } else {
        // There may be duplicate array classes in the boot loader
        for (Iterator<JavaClass> it = boot.getDefinedClasses(); it.hasNext(); ) {
            JavaClass j1 = it.next();
            JavaClass j2 = boot.setArrayType(this, boot, j1);
        }
        // index the boot loader to account for the added files
        boot.initCache();
    }
}
Also used : PortableHeapDumpListener(com.ibm.dtfj.phd.parser.PortableHeapDumpListener) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) CorruptDataException(com.ibm.dtfj.image.CorruptDataException) ImagePointer(com.ibm.dtfj.image.ImagePointer) JavaReference(com.ibm.dtfj.java.JavaReference) LongEnumeration(com.ibm.dtfj.phd.util.LongEnumeration) Iterator(java.util.Iterator) DataUnavailable(com.ibm.dtfj.image.DataUnavailable) JavaMethod(com.ibm.dtfj.java.JavaMethod) MemoryAccessException(com.ibm.dtfj.image.MemoryAccessException) HashSet(java.util.HashSet) MemoryAccessException(com.ibm.dtfj.image.MemoryAccessException) IOException(java.io.IOException) CorruptDataException(com.ibm.dtfj.image.CorruptDataException) JavaClass(com.ibm.dtfj.java.JavaClass) JavaObject(com.ibm.dtfj.java.JavaObject) JavaClassLoader(com.ibm.dtfj.java.JavaClassLoader) CorruptData(com.ibm.dtfj.image.CorruptData) JavaObject(com.ibm.dtfj.java.JavaObject)

Example 2 with PortableHeapDumpListener

use of com.ibm.dtfj.phd.parser.PortableHeapDumpListener in project openj9 by eclipse.

the class PHDJavaHeap method getObjects.

/**
 * Return all the objects in the heap
 * This uses a modified version of the HeapdumpReader which allows abort and resume.
 */
public Iterator<JavaObject> getObjects() {
    final PHDJavaHeap heap = this;
    try {
        return new Iterator<JavaObject>() {

            HeapdumpReader reader = null;

            {
                if (stream == null) {
                    reader = new HeapdumpReader(file, image);
                } else {
                    reader = new HeapdumpReader(stream, image);
                }
            }

            final int adjustLen = reader.version() == 4 && reader.isJ9() ? 1 : 0;

            final long[] current = new long[1];

            static final boolean withRefs = true;

            JavaObject jo;

            int count = 0;

            PortableHeapDumpListener listen = new PortableHeapDumpListener() {

                public void classDump(long address, long superAddress, String name, int size, int flags, int hashCode, LongEnumeration refs) throws Exception {
                }

                public void objectArrayDump(long address, long classAddress, int flags, int hashCode, LongEnumeration refs, int length, long instanceSize) throws Exception {
                    current[0] = address;
                    int refsLen = refs.numberOfElements();
                    int adjustLen2 = Math.min(adjustLen, refsLen);
                    // Use adjustLen for array class so for corrupt Java 5 with 0 refs we have no array class
                    PHDJavaObject.Builder b = new PHDJavaObject.Builder(heap, address, runtime.arrayOf(classAddress, refs, adjustLen), flags, hashCode).instanceSize(instanceSize);
                    jo = withRefs ? b.refs(refs, adjustLen2).length(length - adjustLen2).build() : b.length(length - adjustLen2).build();
                    current[0] = 0;
                    reader.exitParse();
                }

                public void objectDump(long address, long classAddress, int flags, int hashCode, LongEnumeration refs, long instanceSize) throws Exception {
                    current[0] = address;
                    PHDJavaObject.Builder b = new PHDJavaObject.Builder(heap, address, runtime.findClass(classAddress), flags, hashCode).length(PHDJavaObject.SIMPLE_OBJECT).instanceSize(instanceSize);
                    jo = withRefs ? b.refs(refs, 0).build() : b.build();
                    current[0] = 0;
                    reader.exitParse();
                }

                public void primitiveArrayDump(long address, int type, int length, int flags, int hashCode, long instanceSize) throws Exception {
                    current[0] = address;
                    jo = new PHDJavaObject.Builder(heap, address, runtime.findArrayOfType(type), flags, hashCode).refsAsArray(NOREFS, 0).length(length).instanceSize(instanceSize).build();
                    current[0] = 0;
                    reader.exitParse();
                }
            };

            public boolean hasNext() {
                if (jo == null)
                    getNext();
                return jo != null;
            }

            public JavaObject next() {
                if (!hasNext())
                    throw new NoSuchElementException();
                JavaObject ret = jo;
                jo = null;
                ++count;
                return ret;
            }

            private void getNext() {
                try {
                    // but presumes the reader can restart parsing where it left off.
                    if (reader != null && !reader.parse(listen)) {
                        reader.close();
                        reader = null;
                    }
                } catch (EOFException e) {
                    jo = new PHDCorruptJavaObject("Truncated dump found while building object " + count + "/" + reader.totalObjects(), space.getPointer(0), e);
                    reader.close();
                    reader = null;
                } catch (IOException e) {
                    jo = new PHDCorruptJavaObject("Corrupted dump found while building object " + count + "/" + reader.totalObjects(), space.getPointer(0), e);
                    reader.close();
                    reader = null;
                } catch (Exception e) {
                    // Is this right?
                    if (current[0] != 0) {
                        // Only add an exception object the first time it happens
                        // Give up if exception occurs between objects
                        jo = new PHDCorruptJavaObject("Building object " + count + "/" + reader.totalObjects(), space.getPointer(current[0]), e);
                    } else {
                        jo = new PHDCorruptJavaObject("Building object " + count + "/" + reader.totalObjects(), space.getPointer(0), e);
                        reader.close();
                        reader = null;
                    }
                }
            }

            public void remove() {
                throw new UnsupportedOperationException();
            }

            protected void finalize() throws Throwable {
                // but the client doesn't have to run the iterator to the end, so we're accounting for that here
                if (reader != null) {
                    reader.close();
                }
            }
        };
    } catch (IOException e) {
        return new ArrayList<JavaObject>().iterator();
    }
}
Also used : PortableHeapDumpListener(com.ibm.dtfj.phd.parser.PortableHeapDumpListener) HeapdumpReader(com.ibm.dtfj.phd.parser.HeapdumpReader) ArrayList(java.util.ArrayList) IOException(java.io.IOException) IOException(java.io.IOException) EOFException(java.io.EOFException) CorruptDataException(com.ibm.dtfj.image.CorruptDataException) NoSuchElementException(java.util.NoSuchElementException) LongEnumeration(com.ibm.dtfj.phd.util.LongEnumeration) JavaObject(com.ibm.dtfj.java.JavaObject) Iterator(java.util.Iterator) EOFException(java.io.EOFException) NoSuchElementException(java.util.NoSuchElementException)

Example 3 with PortableHeapDumpListener

use of com.ibm.dtfj.phd.parser.PortableHeapDumpListener in project openj9 by eclipse.

the class PHDJavaClassLoader method processData.

private void processData(HeapdumpReader reader, final PHDImage parentImage, final ImageAddressSpace space, final PHDJavaRuntime runtime) throws IOException {
    final JavaClassLoader loader = this;
    final int adjustLen = reader.version() == 4 && reader.isJ9() ? 1 : 0;
    final int[] realClasses = new int[1];
    try {
        reader.parse(new PortableHeapDumpListener() {

            long prevAddress;

            PHDJavaClass prevObjClass;

            private void updateSizes(long address) {
                if (prevObjClass != null)
                    prevObjClass.updateSize(prevAddress, address);
                prevObjClass = null;
                prevAddress = address;
            }

            public void classDump(long address, long superAddress, String name, int size, int flags, int hashCode, LongEnumeration refs) throws Exception {
                updateSizes(address);
                classes.put(address, new PHDJavaClass.Builder(space, runtime, loader, address, superAddress, name).size(size).flags(flags).hashCode(hashCode).refs(refs).build());
                updateAddresses(address, size, name);
                ++realClasses[0];
            }

            public void objectArrayDump(long address, long classAddress, int flags, int hashCode, LongEnumeration refs, int length, long instanceSize) throws Exception {
                int refsLen = refs.numberOfElements();
                int adjustLen2 = Math.min(adjustLen, refsLen);
                updateSizes(address);
                updateAddresses(address, classAddress, length - adjustLen2);
                long classAddress2 = adjustLen2 == 1 ? refs.nextLong() : 0;
                genArrayClasses(space, runtime, loader, adjustLen2, classAddress, classAddress2);
            }

            public void objectDump(long address, long classAddress, int flags, int hashCode, LongEnumeration refs, long instanceSize) throws Exception {
                updateSizes(address);
                updateAddresses(address, classAddress, -1);
                genObjectClass(space, runtime, loader, classAddress, hashCode);
            }

            public void primitiveArrayDump(long address, int type, int length, int flags, int hashCode, long instanceSize) throws Exception {
                updateSizes(address);
                updateAddresses(address, type, length);
            }

            private void genObjectClass(final ImageAddressSpace space, final PHDJavaRuntime runtime, final JavaClassLoader loader, long classAddress, int hashCode) {
                if (!classes.containsKey(classAddress)) {
                    PHDJavaClass objClass = new PHDJavaClass.Builder(space, runtime, loader, classAddress, PHDJavaClass.UNKNOWN_SUPERCLASS, PHDJavaClass.UNKNOWN_NONARRAY).build();
                    classes.put(classAddress, objClass);
                    updateAddresses(classAddress, 100, null);
                }
                prevObjClass = (PHDJavaClass) findClass(classAddress);
            }

            private PHDJavaClass genArrayClass(final ImageAddressSpace space, final PHDJavaRuntime runtime, final JavaClassLoader loader, long classAddress, long sup, String name) {
                PHDJavaClass elemCls;
                int size = 100;
                elemCls = new PHDJavaClass.Builder(space, runtime, loader, classAddress, sup, name).build();
                classes.put(classAddress, elemCls);
                updateAddresses(classAddress, size, name);
                return elemCls;
            }

            private void genArrayClasses(final ImageAddressSpace space, final PHDJavaRuntime runtime, final JavaClassLoader loader, final int adjustLen, long classAddress, long classAddress2) {
                if (adjustLen == 1) {
                    // Java 5.0 arrays with type = base component type e.g. String
                    // First reference = actual array type e.g. [[Ljava.lang.String;
                    JavaClass arrayCls;
                    if (!classes.containsKey(classAddress2)) {
                        String name = PHDJavaClass.UNKNOWN_ARRAY;
                        arrayCls = genArrayClass(space, runtime, loader, classAddress2, jlo, name);
                    } else {
                        arrayCls = findClass(classAddress2);
                    }
                    arrayClasses.put(classAddress, arrayCls);
                    if (!classes.containsKey(classAddress)) {
                        String name = PHDJavaClass.UNKNOWN_NONARRAY;
                        genArrayClass(space, runtime, loader, classAddress, PHDJavaClass.UNKNOWN_SUPERCLASS, name);
                    }
                } else {
                    arrayClasses.put(classAddress, null);
                }
                return;
            }
        });
    } catch (EOFException e) {
        classes.put(runtime.nextDummyClassAddr(), new PHDCorruptJavaClass("Truncated dump found building class " + realClasses[0], null, e));
    } catch (IOException e) {
        classes.put(runtime.nextDummyClassAddr(), new PHDCorruptJavaClass("Corrupted dump found building class " + realClasses[0], null, e));
    } catch (Exception e) {
        classes.put(runtime.nextDummyClassAddr(), new PHDCorruptJavaClass("Building class " + realClasses[0], null, e));
    } finally {
        reader.close();
        reader = null;
    }
    jlo = 0;
    // Use an uncached search as the index hasn't been built.
    JavaClass jco = findClassUncached("java/lang/Object");
    if (jco != null) {
        ImagePointer ip = jco.getID();
        if (ip != null)
            jlo = ip.getAddress();
    } else {
        // If the dump is very corrupt it won't have java.lang.Object - so create one
        jco = new PHDJavaClass.Builder(space, runtime, loader, 0, 0, "java/lang/Object").build();
        jlo = runtime.nextDummyClassAddr();
        classes.put(jlo, jco);
    }
    // If the dump is very corrupt it won't have java.lang.Class - so create one
    JavaClass jcl = findClassUncached("java/lang/Class");
    if (jcl == null) {
        jcl = new PHDJavaClass.Builder(space, runtime, loader, 0, jlo, "java/lang/Class").build();
        classes.put(runtime.nextDummyClassAddr(), jcl);
    }
    // nor will it have primitive array classes
    for (int i = 0; i < PHDJavaRuntime.arrayTypeName.length; ++i) {
        JavaClass jc = findClassUncached(PHDJavaRuntime.arrayTypeName[i]);
        if (jc == null) {
            jc = new PHDJavaClass.Builder(space, runtime, loader, 0, jlo, PHDJavaRuntime.arrayTypeName[i]).build();
            classes.put(runtime.nextDummyClassAddr(), jc);
        }
    }
    // Bug in PHD dumps - some Java 6 types have the type of an array being the whole array, not the elements
    // Is the type of the array the whole array or the type of an element?
    boolean arrayTypeIsArray = true;
    for (Long id : arrayClasses.keySet()) {
        JavaClass cl1 = findClass(id);
        // Corrupt dump might not have the class!
        if (cl1 == null)
            continue;
        try {
            if (!cl1.isArray()) {
                arrayTypeIsArray = false;
            }
        } catch (CorruptDataException e) {
            // If we don't know the type then presume they are not arrays
            arrayTypeIsArray = false;
        }
    }
    // Create a mapping from the phd id of an array object to the type of the whole array
    for (Long id : arrayClasses.keySet()) {
        JavaClass cl1 = findClass(id);
        if (cl1 == null) {
            String name = arrayTypeIsArray ? PHDJavaClass.UNKNOWN_ARRAY : null;
            long sup = arrayTypeIsArray ? jlo : PHDJavaClass.UNKNOWN_SUPERCLASS;
            cl1 = new PHDJavaClass.Builder(space, runtime, loader, id, sup, name).build();
            classes.put(id, cl1);
        }
        JavaClass ar = arrayClasses.get(id);
        if (ar != null) {
            ImagePointer ip = ar.getID();
            if (ip != null) {
                JavaClass ar2 = findClass(ip.getAddress());
                if (ar2 != null) {
                    ar = ar2;
                }
            }
        // cl1 is not a component type for multidimensional arrays, but is the scalar type
        // ((PHDJavaClass)ar).setComponentType(cl1);
        }
        JavaClass cl2;
        if (arrayTypeIsArray) {
            cl2 = cl1;
        } else if (ar != null) {
            cl2 = ar;
        } else {
            try {
                String name = cl1.getName();
                String arrayName = arrayName(name);
                Set<JavaClass> s = findClasses(arrayName);
                if (s.size() == 0) {
                    // Array class doesn't exist, so create a dummy one
                    cl2 = new PHDJavaClass.Builder(space, runtime, loader, 0, jlo, arrayName).componentType(cl1).build();
                } else if (s.size() == 1) {
                    // Only one, so use it
                    cl2 = s.iterator().next();
                } else {
                    // Multiple classes, so if possible choose one
                    cl2 = null;
                    for (JavaClass cl3 : s) {
                        // If so then it is the one.
                        if (PHDJavaClass.referencesClass(cl3, cl1)) {
                            cl2 = cl3;
                            break;
                        }
                    }
                }
            } catch (CorruptDataException e) {
                // Array class doesn't exist, so create a dummy one
                cl2 = new PHDJavaClass.Builder(space, runtime, loader, 0, jlo, PHDJavaClass.UNKNOWN_ARRAY).componentType(cl1).build();
            }
            if (cl2 instanceof PHDJavaClass) {
                // We know the component type, so remember it for later
                ((PHDJavaClass) cl2).setComponentType(cl1);
            }
        }
        // Even if the array class is null (we couldn't decide), mark it so we know for later
        arrayClasses.put(id, cl2);
    }
    initCache();
}
Also used : PortableHeapDumpListener(com.ibm.dtfj.phd.parser.PortableHeapDumpListener) Set(java.util.Set) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) IOException(java.io.IOException) CorruptDataException(com.ibm.dtfj.image.CorruptDataException) IOException(java.io.IOException) EOFException(java.io.EOFException) CorruptDataException(com.ibm.dtfj.image.CorruptDataException) ImageAddressSpace(com.ibm.dtfj.image.ImageAddressSpace) ImagePointer(com.ibm.dtfj.image.ImagePointer) LongEnumeration(com.ibm.dtfj.phd.util.LongEnumeration) JavaClassLoader(com.ibm.dtfj.java.JavaClassLoader) JavaClass(com.ibm.dtfj.java.JavaClass) EOFException(java.io.EOFException)

Aggregations

CorruptDataException (com.ibm.dtfj.image.CorruptDataException)3 PortableHeapDumpListener (com.ibm.dtfj.phd.parser.PortableHeapDumpListener)3 LongEnumeration (com.ibm.dtfj.phd.util.LongEnumeration)3 IOException (java.io.IOException)3 ImagePointer (com.ibm.dtfj.image.ImagePointer)2 JavaClass (com.ibm.dtfj.java.JavaClass)2 JavaClassLoader (com.ibm.dtfj.java.JavaClassLoader)2 JavaObject (com.ibm.dtfj.java.JavaObject)2 EOFException (java.io.EOFException)2 HashSet (java.util.HashSet)2 Iterator (java.util.Iterator)2 CorruptData (com.ibm.dtfj.image.CorruptData)1 DataUnavailable (com.ibm.dtfj.image.DataUnavailable)1 ImageAddressSpace (com.ibm.dtfj.image.ImageAddressSpace)1 MemoryAccessException (com.ibm.dtfj.image.MemoryAccessException)1 JavaMethod (com.ibm.dtfj.java.JavaMethod)1 JavaReference (com.ibm.dtfj.java.JavaReference)1 HeapdumpReader (com.ibm.dtfj.phd.parser.HeapdumpReader)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1