/electric-8.09/com/sun/electric/database/DumpHeap.java
Java | 346 lines | 270 code | 28 blank | 48 comment | 82 complexity | a6f142bd6413c3de336c5a7564a73faf MD5 | raw file
Possible License(s): GPL-3.0
- /* -*- tab-width: 4 -*-
- *
- * Electric(tm) VLSI Design System
- *
- * File: DumpHeap.java
- * Written by: Dmitry Nadezhin, Sun Microsystems.
- *
- * Copyright (c) 2003 Sun Microsystems and Static Free Software
- *
- * Electric(tm) is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Electric(tm) 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 for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Electric(tm); see the file COPYING. If not, write to
- * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
- * Boston, Mass 02111-1307, USA.
- */
- package com.sun.electric.database;
- import com.sun.electric.database.geometry.GenMath;
- import java.io.BufferedOutputStream;
- import java.io.DataOutputStream;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.Serializable;
- import java.lang.ref.Reference;
- import java.lang.reflect.Field;
- import java.lang.reflect.Modifier;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.Collection;
- import java.util.HashMap;
- import java.util.Iterator;
- import java.util.Map;
- /**
- * Class to dump JVM heap.
- */
- public class DumpHeap {
- private static final boolean REFERENCES = false;
-
- private int[] objHash = new int[1];
- private ArrayList<Object> objs = (new ArrayList<Object>());
- { objs.add(null); }
- private HashMap<Class,ClassDescriptor> classes = new HashMap<Class,ClassDescriptor>();
-
- private DumpHeap() {}
-
- /**
- * Method to dump JVM heap.
- */
- public static void dump(String fileName)
- {
- try {
- System.gc();
- DumpHeap dumpHeap = new DumpHeap();
- dumpHeap.handler(ClassLoader.class);
- dumpHeap.sweeps(100);
- DataOutputStream s = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(fileName)));
- try {
- dumpHeap.write(s);
- } finally {
- s.close();
- }
- } catch (SecurityException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- }
- }
- private ClassDescriptor classDescriptorOf(Class cls) {
- ClassDescriptor cd = classes.get(cls);
- if (cd == null) {
- cd = new ClassDescriptor(cls);
- classes.put(cls, cd);
- }
- return cd;
- }
-
- private int handler(Object obj) { return handler(obj, true); }
- private int handler0(Object obj) { return handler(obj, false); }
-
- private int handler(Object obj, boolean create) {
- if (obj == null) return 0;
- int i = System.identityHashCode(obj) & 0x7FFFFFFF;
- i %= objHash.length;
- for (int j = 1; objHash[i] != 0; j += 2) {
- Object o = objs.get(objHash[i]);
- if (o == obj) return objHash[i];
- i += j;
- if (i >= objHash.length) i -= objHash.length;
- }
- if (!create) return 0;
-
- if (objs.size()*2 <= objHash.length - 3) {
- objHash[i] = objs.size();
- objs.add(obj);
- return i;
- }
-
- rehash();
- return handler(obj);
- }
-
- void rehash() {
- int newSize = objs.size()*2 + 3;
- if (newSize < 0) throw new IndexOutOfBoundsException();
- int[] newObjHash = new int[GenMath.primeSince(newSize)];
- for (int k = 0; k < objs.size(); k++) {
- Object obj = objs.get(k);
- int i = System.identityHashCode(obj) & 0x7FFFFFFF;
- i %= newObjHash.length;
- for (int j = 1; newObjHash[i] != 0; j += 2) {
- assert objs.get(newObjHash[i]) != obj;
- i += j;
- if (i >= newObjHash.length) i -= newObjHash.length;
- }
- newObjHash[i] = k;
- }
- objHash = newObjHash;
- }
-
- private void sweep()
- throws SecurityException, IllegalAccessException
- {
- for (int scanned = 1; scanned < objs.size(); scanned++) {
- Object obj = objs.get(scanned);
-
- handler(obj.getClass());
- if (obj instanceof Object[]) {
- Object[] array = (Object[])obj;
- for (int i = 0; i < array.length; i++)
- handler(array[i]);
- } else if (obj instanceof Collection) {
- Collection coll = (Collection)obj;
- for (Iterator it = coll.iterator(); it.hasNext(); )
- handler(it.next());
- } else if (obj instanceof Map) {
- Map map = (Map)obj;
- for (Iterator it = map.entrySet().iterator(); it.hasNext(); ) {
- Map.Entry entry = (Map.Entry)it.next();
- handler(entry.getKey());
- handler(entry.getValue());
- }
- } else if (obj instanceof String) {
- } else {
- Class cls = obj.getClass();
- ClassDescriptor cd = classDescriptorOf(cls);
- for (int i = 0; i < cd.fields.length; i++) {
- Field f = cd.fields[i];
- handler(f.get(obj));
- }
- if (obj instanceof Class) {
- cls = (Class)obj;
- cd = classDescriptorOf(cls);
-
- handler(cls.getComponentType());
- handler(cls.getSuperclass());
- // handler(cls.getEnclosingClass());
- for (int i = 0; i < cd.staticFields.length; i++) {
- Field f = cd.staticFields[i];
- handler(f.get(null));
- }
- }
- }
- }
- }
-
- // private void reflectClass(Class cls)
- // throws SecurityException, IllegalAccessException
- // {
- //
- // Field[] fields = cls.getDeclaredFields();
- // for (int i = 0; i < fields.length; i++) {
- // Field f = fields[i];
- // int fm = f.getModifiers();
- // if (!Modifier.isStatic(fm)) continue;
- // Class tf = f.getType();
- // if (tf.isPrimitive()) continue;
- // f.setAccessible(true);
- // Object value = f.get(null);
- // handler(value);
- // }
- // }
-
- private void sweeps(int maxSweep)
- throws SecurityException, IllegalAccessException
- {
- int numSweep = 0;
- for (;;) {
- int numObjects = objs.size();
- sweep();
- if (++numSweep >= maxSweep) break;
- if (objs.size() == numObjects) break;
- }
- System.out.println(numSweep + " sweeps");
- }
-
- private void write(DataOutputStream out)
- throws IOException, IllegalAccessException
- {
- int numObjs = objs.size() - 1;
- out.writeInt(numObjs);
- for (Iterator it = classes.values().iterator(); it.hasNext(); ) {
- ClassDescriptor cd = (ClassDescriptor)it.next();
- Class cls = cd.cls;
- int h = handler0(cd.cls);
- assert h != 0;
- out.writeInt(h);
- out.writeUTF(cd.cls.getName());
- int mode;
- if (cls.isArray() && !cls.getComponentType().isPrimitive()) {
- mode = MyClass.ARRAY;
- } else if (Collection.class.isAssignableFrom(cls)) {
- mode = MyClass.ARRAY;
- } else if (Map.class.isAssignableFrom(cls)) {
- mode = MyClass.MAP;
- } else if (cls == String.class) {
- mode = MyClass.STRING;
- } else if (cls == Class.class) {
- mode = MyClass.CLASS;
- } else {
- mode = MyClass.NORMAL;
- }
- out.writeByte(mode);
- out.writeInt(cd.staticFields.length);
- for (int i = 0; i < cd.staticFields.length; i++)
- out.writeUTF(cd.staticFields[i].getName());
- out.writeInt(cd.fields.length);
- for (int i = 0; i < cd.fields.length; i++)
- out.writeUTF(cd.fields[i].getName());
- }
- out.writeInt(0);
-
- for (int h = 1; h <= numObjs; h++) {
- Object obj = objs.get(h);
- if (obj instanceof String) {
- out.writeInt(h);
- out.writeUTF((String)obj);
- }
- }
- out.writeInt(0);
-
- for (int h = 1; h <= numObjs; h++) {
- Object obj = objs.get(h);
- out.writeInt(handler0(obj.getClass()));
- if (obj instanceof Object[]) {
- Object[] array = (Object[])obj;
- out.writeInt(array.length);
- for (int i = 0; i < array.length; i++)
- out.writeInt(handler0(array[i]));
- } else if (obj instanceof Collection) {
- Collection coll = (Collection)obj;
- int length = coll.size();
- out.writeInt(length);
- int i = 0;
- for (Iterator it = coll.iterator(); i < length && it.hasNext(); i++)
- out.writeInt(handler0(it.next()));
- while (i < length) out.writeInt(0);
- } else if (obj instanceof Map) {
- Map map = (Map)obj;
- int length = 0;
- out.writeInt(length);
- int i = 0;
- for (Iterator it = map.entrySet().iterator(); i < length && it.hasNext(); i++) {
- Map.Entry entry = (Map.Entry)it.next();
- out.writeInt(handler0(entry.getKey()));
- out.writeInt(handler0(entry.getValue()));
- }
- while (i < length) { out.writeInt(0); out.writeInt(0); }
- } else if (obj instanceof String) {
- } else {
- Class cls = obj.getClass();
- ClassDescriptor cd = classDescriptorOf(cls);
- for (int i = 0; i < cd.fields.length; i++) {
- Field f = cd.fields[i];
- out.writeInt(handler0(f.get(obj)));
- }
- if (obj instanceof Class) {
- cd = classDescriptorOf((Class)obj);
- for (int i = 0; i < cd.staticFields.length; i++) {
- Field f = cd.staticFields[i];
- out.writeInt(handler0(f.get(null)));
- }
- }
- }
- }
- out.writeInt(0);
- }
-
- private class ClassDescriptor implements Serializable {
- private final Class cls;
- private final Field[] fields;
- private final Field[] staticFields;
- // private int numObjects;
-
- private ClassDescriptor(Class cls) {
- this.cls = cls;
- ArrayList<Field> fieldList = new ArrayList<Field>();
- ArrayList<Field> staticFieldList = new ArrayList<Field>();
- Class superCls = cls.getSuperclass();
- if (superCls != null)
- fieldList.addAll(Arrays.asList(classDescriptorOf(superCls).fields));
- Field[] flds;
- try {
- flds = cls.getDeclaredFields();
- } catch (NoClassDefFoundError e) {
- System.out.println("Can't getDeclaredFields in " + cls);
- flds = new Field[0];
- }
- for (int i = 0; i < flds.length; i++) {
- Field f = flds[i];
- Class tf = f.getType();
- if (tf.isPrimitive()) continue;
- if (!REFERENCES && Reference.class.isAssignableFrom(cls) && f.getName().equals("referent"))
- continue;
- f.setAccessible(true);
- int fm = f.getModifiers();
- if (Modifier.isStatic(fm))
- staticFieldList.add(f);
- else
- fieldList.add(f);
- }
- Field[] NULL_FIELD_ARRAY = {};
- this.fields = fieldList.toArray(NULL_FIELD_ARRAY);
- this.staticFields = staticFieldList.toArray(NULL_FIELD_ARRAY);
- }
- }
-
- }