package org.jblooming.tracer; import org.jblooming.ontology.Identifiable; import org.jblooming.waf.SessionState; import java.lang.reflect.Field; import java.lang.reflect.Array; import java.lang.reflect.Modifier; import java.util.Map; import java.util.Stack; import java.util.IdentityHashMap; /** * (c) Open Lab - www.open-lab.com * Date: Apr 2, 2007 * Time: 10:24:08 AM */ /** * This class can estimate how much memory an Object uses. It is * fairly accurate for JDK 1.4.2. It is based on the newsletter #29. */ public class MemoryCounter { private static final MemorySizes sizes = new MemorySizes(); private final Map visited = new IdentityHashMap(); private final Stack stack = new Stack(); public synchronized long estimate(Object obj, boolean includeStatic) { assert visited.isEmpty(); assert stack.isEmpty(); long result = _estimate(obj,includeStatic); while (!stack.isEmpty()) { Object localObj = stack.pop(); long localEstimate = _estimate(localObj,includeStatic); result += localEstimate; } visited.clear(); return result; } private boolean skipObject(Object obj) { if (obj instanceof String) { // this will not cause a memory leak since // unused interned Strings will be thrown away if (obj == ((String) obj).intern()) { return true; } } return (obj == null) || visited.containsKey(obj); } private long _estimate(Object obj, boolean includeStatic) { if (skipObject(obj)) return 0; visited.put(obj, null); long result = 0; Class clazz = obj.getClass(); if (clazz.isArray()) { return _estimateArray(obj,includeStatic); } while (clazz != null) { Field[] fields = clazz.getDeclaredFields(); for (int i = 0; i < fields.length; i++) { if (includeStatic || !Modifier.isStatic(fields[i].getModifiers())) { if (fields[i].getType().isPrimitive()) { result += sizes.getPrimitiveFieldSize( fields[i].getType()); } else { result += sizes.getPointerSize(); fields[i].setAccessible(true); try { //if (localEstimate > 1024) // System.out.println(localObj.getClass().getSimpleName()+ " "+Tracer.objectSize(localEstimate)); //System.out.println(fields[i].getName()); Object toBeDone = fields[i].get(obj); if (toBeDone != null && !(toBeDone instanceof Identifiable)) { stack.add(toBeDone); } } catch (IllegalAccessException ex) { assert false; } } } } clazz = clazz.getSuperclass(); } result += sizes.getClassSize(); long l = roundUpToNearestEightBytes(result); return l; } private long roundUpToNearestEightBytes(long result) { if ((result % 8) != 0) { result += 8 - (result % 8); } return result; } protected long _estimateArray(Object obj, boolean includeStatic) { long result = 16; int length = Array.getLength(obj); if (length != 0) { Class arrayElementClazz = obj.getClass().getComponentType(); if (arrayElementClazz.isPrimitive()) { result += length * sizes.getPrimitiveArrayElementSize(arrayElementClazz); } else { for (int i = 0; i < length; i++) { result += sizes.getPointerSize() + _estimate(Array.get(obj, i),includeStatic); } } } return result; } }