PageRenderTime 86ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/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
  1. /* -*- tab-width: 4 -*-
  2. *
  3. * Electric(tm) VLSI Design System
  4. *
  5. * File: DumpHeap.java
  6. * Written by: Dmitry Nadezhin, Sun Microsystems.
  7. *
  8. * Copyright (c) 2003 Sun Microsystems and Static Free Software
  9. *
  10. * Electric(tm) is free software; you can redistribute it and/or modify
  11. * it under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation; either version 3 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * Electric(tm) is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with Electric(tm); see the file COPYING. If not, write to
  22. * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  23. * Boston, Mass 02111-1307, USA.
  24. */
  25. package com.sun.electric.database;
  26. import com.sun.electric.database.geometry.GenMath;
  27. import java.io.BufferedOutputStream;
  28. import java.io.DataOutputStream;
  29. import java.io.FileOutputStream;
  30. import java.io.IOException;
  31. import java.io.Serializable;
  32. import java.lang.ref.Reference;
  33. import java.lang.reflect.Field;
  34. import java.lang.reflect.Modifier;
  35. import java.util.ArrayList;
  36. import java.util.Arrays;
  37. import java.util.Collection;
  38. import java.util.HashMap;
  39. import java.util.Iterator;
  40. import java.util.Map;
  41. /**
  42. * Class to dump JVM heap.
  43. */
  44. public class DumpHeap {
  45. private static final boolean REFERENCES = false;
  46. private int[] objHash = new int[1];
  47. private ArrayList<Object> objs = (new ArrayList<Object>());
  48. { objs.add(null); }
  49. private HashMap<Class,ClassDescriptor> classes = new HashMap<Class,ClassDescriptor>();
  50. private DumpHeap() {}
  51. /**
  52. * Method to dump JVM heap.
  53. */
  54. public static void dump(String fileName)
  55. {
  56. try {
  57. System.gc();
  58. DumpHeap dumpHeap = new DumpHeap();
  59. dumpHeap.handler(ClassLoader.class);
  60. dumpHeap.sweeps(100);
  61. DataOutputStream s = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(fileName)));
  62. try {
  63. dumpHeap.write(s);
  64. } finally {
  65. s.close();
  66. }
  67. } catch (SecurityException e) {
  68. e.printStackTrace();
  69. } catch (IOException e) {
  70. e.printStackTrace();
  71. } catch (IllegalAccessException e) {
  72. e.printStackTrace();
  73. }
  74. }
  75. private ClassDescriptor classDescriptorOf(Class cls) {
  76. ClassDescriptor cd = classes.get(cls);
  77. if (cd == null) {
  78. cd = new ClassDescriptor(cls);
  79. classes.put(cls, cd);
  80. }
  81. return cd;
  82. }
  83. private int handler(Object obj) { return handler(obj, true); }
  84. private int handler0(Object obj) { return handler(obj, false); }
  85. private int handler(Object obj, boolean create) {
  86. if (obj == null) return 0;
  87. int i = System.identityHashCode(obj) & 0x7FFFFFFF;
  88. i %= objHash.length;
  89. for (int j = 1; objHash[i] != 0; j += 2) {
  90. Object o = objs.get(objHash[i]);
  91. if (o == obj) return objHash[i];
  92. i += j;
  93. if (i >= objHash.length) i -= objHash.length;
  94. }
  95. if (!create) return 0;
  96. if (objs.size()*2 <= objHash.length - 3) {
  97. objHash[i] = objs.size();
  98. objs.add(obj);
  99. return i;
  100. }
  101. rehash();
  102. return handler(obj);
  103. }
  104. void rehash() {
  105. int newSize = objs.size()*2 + 3;
  106. if (newSize < 0) throw new IndexOutOfBoundsException();
  107. int[] newObjHash = new int[GenMath.primeSince(newSize)];
  108. for (int k = 0; k < objs.size(); k++) {
  109. Object obj = objs.get(k);
  110. int i = System.identityHashCode(obj) & 0x7FFFFFFF;
  111. i %= newObjHash.length;
  112. for (int j = 1; newObjHash[i] != 0; j += 2) {
  113. assert objs.get(newObjHash[i]) != obj;
  114. i += j;
  115. if (i >= newObjHash.length) i -= newObjHash.length;
  116. }
  117. newObjHash[i] = k;
  118. }
  119. objHash = newObjHash;
  120. }
  121. private void sweep()
  122. throws SecurityException, IllegalAccessException
  123. {
  124. for (int scanned = 1; scanned < objs.size(); scanned++) {
  125. Object obj = objs.get(scanned);
  126. handler(obj.getClass());
  127. if (obj instanceof Object[]) {
  128. Object[] array = (Object[])obj;
  129. for (int i = 0; i < array.length; i++)
  130. handler(array[i]);
  131. } else if (obj instanceof Collection) {
  132. Collection coll = (Collection)obj;
  133. for (Iterator it = coll.iterator(); it.hasNext(); )
  134. handler(it.next());
  135. } else if (obj instanceof Map) {
  136. Map map = (Map)obj;
  137. for (Iterator it = map.entrySet().iterator(); it.hasNext(); ) {
  138. Map.Entry entry = (Map.Entry)it.next();
  139. handler(entry.getKey());
  140. handler(entry.getValue());
  141. }
  142. } else if (obj instanceof String) {
  143. } else {
  144. Class cls = obj.getClass();
  145. ClassDescriptor cd = classDescriptorOf(cls);
  146. for (int i = 0; i < cd.fields.length; i++) {
  147. Field f = cd.fields[i];
  148. handler(f.get(obj));
  149. }
  150. if (obj instanceof Class) {
  151. cls = (Class)obj;
  152. cd = classDescriptorOf(cls);
  153. handler(cls.getComponentType());
  154. handler(cls.getSuperclass());
  155. // handler(cls.getEnclosingClass());
  156. for (int i = 0; i < cd.staticFields.length; i++) {
  157. Field f = cd.staticFields[i];
  158. handler(f.get(null));
  159. }
  160. }
  161. }
  162. }
  163. }
  164. // private void reflectClass(Class cls)
  165. // throws SecurityException, IllegalAccessException
  166. // {
  167. //
  168. // Field[] fields = cls.getDeclaredFields();
  169. // for (int i = 0; i < fields.length; i++) {
  170. // Field f = fields[i];
  171. // int fm = f.getModifiers();
  172. // if (!Modifier.isStatic(fm)) continue;
  173. // Class tf = f.getType();
  174. // if (tf.isPrimitive()) continue;
  175. // f.setAccessible(true);
  176. // Object value = f.get(null);
  177. // handler(value);
  178. // }
  179. // }
  180. private void sweeps(int maxSweep)
  181. throws SecurityException, IllegalAccessException
  182. {
  183. int numSweep = 0;
  184. for (;;) {
  185. int numObjects = objs.size();
  186. sweep();
  187. if (++numSweep >= maxSweep) break;
  188. if (objs.size() == numObjects) break;
  189. }
  190. System.out.println(numSweep + " sweeps");
  191. }
  192. private void write(DataOutputStream out)
  193. throws IOException, IllegalAccessException
  194. {
  195. int numObjs = objs.size() - 1;
  196. out.writeInt(numObjs);
  197. for (Iterator it = classes.values().iterator(); it.hasNext(); ) {
  198. ClassDescriptor cd = (ClassDescriptor)it.next();
  199. Class cls = cd.cls;
  200. int h = handler0(cd.cls);
  201. assert h != 0;
  202. out.writeInt(h);
  203. out.writeUTF(cd.cls.getName());
  204. int mode;
  205. if (cls.isArray() && !cls.getComponentType().isPrimitive()) {
  206. mode = MyClass.ARRAY;
  207. } else if (Collection.class.isAssignableFrom(cls)) {
  208. mode = MyClass.ARRAY;
  209. } else if (Map.class.isAssignableFrom(cls)) {
  210. mode = MyClass.MAP;
  211. } else if (cls == String.class) {
  212. mode = MyClass.STRING;
  213. } else if (cls == Class.class) {
  214. mode = MyClass.CLASS;
  215. } else {
  216. mode = MyClass.NORMAL;
  217. }
  218. out.writeByte(mode);
  219. out.writeInt(cd.staticFields.length);
  220. for (int i = 0; i < cd.staticFields.length; i++)
  221. out.writeUTF(cd.staticFields[i].getName());
  222. out.writeInt(cd.fields.length);
  223. for (int i = 0; i < cd.fields.length; i++)
  224. out.writeUTF(cd.fields[i].getName());
  225. }
  226. out.writeInt(0);
  227. for (int h = 1; h <= numObjs; h++) {
  228. Object obj = objs.get(h);
  229. if (obj instanceof String) {
  230. out.writeInt(h);
  231. out.writeUTF((String)obj);
  232. }
  233. }
  234. out.writeInt(0);
  235. for (int h = 1; h <= numObjs; h++) {
  236. Object obj = objs.get(h);
  237. out.writeInt(handler0(obj.getClass()));
  238. if (obj instanceof Object[]) {
  239. Object[] array = (Object[])obj;
  240. out.writeInt(array.length);
  241. for (int i = 0; i < array.length; i++)
  242. out.writeInt(handler0(array[i]));
  243. } else if (obj instanceof Collection) {
  244. Collection coll = (Collection)obj;
  245. int length = coll.size();
  246. out.writeInt(length);
  247. int i = 0;
  248. for (Iterator it = coll.iterator(); i < length && it.hasNext(); i++)
  249. out.writeInt(handler0(it.next()));
  250. while (i < length) out.writeInt(0);
  251. } else if (obj instanceof Map) {
  252. Map map = (Map)obj;
  253. int length = 0;
  254. out.writeInt(length);
  255. int i = 0;
  256. for (Iterator it = map.entrySet().iterator(); i < length && it.hasNext(); i++) {
  257. Map.Entry entry = (Map.Entry)it.next();
  258. out.writeInt(handler0(entry.getKey()));
  259. out.writeInt(handler0(entry.getValue()));
  260. }
  261. while (i < length) { out.writeInt(0); out.writeInt(0); }
  262. } else if (obj instanceof String) {
  263. } else {
  264. Class cls = obj.getClass();
  265. ClassDescriptor cd = classDescriptorOf(cls);
  266. for (int i = 0; i < cd.fields.length; i++) {
  267. Field f = cd.fields[i];
  268. out.writeInt(handler0(f.get(obj)));
  269. }
  270. if (obj instanceof Class) {
  271. cd = classDescriptorOf((Class)obj);
  272. for (int i = 0; i < cd.staticFields.length; i++) {
  273. Field f = cd.staticFields[i];
  274. out.writeInt(handler0(f.get(null)));
  275. }
  276. }
  277. }
  278. }
  279. out.writeInt(0);
  280. }
  281. private class ClassDescriptor implements Serializable {
  282. private final Class cls;
  283. private final Field[] fields;
  284. private final Field[] staticFields;
  285. // private int numObjects;
  286. private ClassDescriptor(Class cls) {
  287. this.cls = cls;
  288. ArrayList<Field> fieldList = new ArrayList<Field>();
  289. ArrayList<Field> staticFieldList = new ArrayList<Field>();
  290. Class superCls = cls.getSuperclass();
  291. if (superCls != null)
  292. fieldList.addAll(Arrays.asList(classDescriptorOf(superCls).fields));
  293. Field[] flds;
  294. try {
  295. flds = cls.getDeclaredFields();
  296. } catch (NoClassDefFoundError e) {
  297. System.out.println("Can't getDeclaredFields in " + cls);
  298. flds = new Field[0];
  299. }
  300. for (int i = 0; i < flds.length; i++) {
  301. Field f = flds[i];
  302. Class tf = f.getType();
  303. if (tf.isPrimitive()) continue;
  304. if (!REFERENCES && Reference.class.isAssignableFrom(cls) && f.getName().equals("referent"))
  305. continue;
  306. f.setAccessible(true);
  307. int fm = f.getModifiers();
  308. if (Modifier.isStatic(fm))
  309. staticFieldList.add(f);
  310. else
  311. fieldList.add(f);
  312. }
  313. Field[] NULL_FIELD_ARRAY = {};
  314. this.fields = fieldList.toArray(NULL_FIELD_ARRAY);
  315. this.staticFields = staticFieldList.toArray(NULL_FIELD_ARRAY);
  316. }
  317. }
  318. }