package claudius; import java.io.*; import java.util.*; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import javax.servlet.http.*; public class HttpSessionMetrics implements HttpSessionActivationListener, HttpSessionAttributeListener { public static final int EACH_OBJECT =0; public static final int USE_MAP = 1; public static final int DEFAULT = USE_MAP; String se; public void sessionWillPassivate(HttpSessionEvent se) { log("sessionWillPassivate: session size = " + calculateSessionSize(se.getSession(), DEFAULT)); } public void sessionDidActivate(HttpSessionEvent se) { log("sessionDidActivate: session size = " + calculateSessionSize(se.getSession(), DEFAULT)); } public void attributeAdded(HttpSessionBindingEvent se) { log("attributeAdded [" + se.getName() + " = " + se.getValue() + "]: session size = " + calculateSessionSize(se.getSession(), DEFAULT)); } public void attributeRemoved(HttpSessionBindingEvent se) { log("attributeRemoved [" + se.getName() + " = " + se.getValue() + "]: session size = " + calculateSessionSize(se.getSession(), DEFAULT)); } public void attributeReplaced(HttpSessionBindingEvent se) { log("attributeReplaced [" + se.getName() + " = " + se.getValue() + "]: session size = " + calculateSessionSize(se.getSession(), DEFAULT)); } static void log(Object m) { System.out.println("---- HttpSessionMetrics --- " + m); } int calculateSessionSize(HttpSession hs, int mode) { int size = -1; if (mode == USE_MAP) { size = calculateSessionSizeThroughMap(hs); } else if (mode == EACH_OBJECT) { size = calculateSessionSizePerObject(hs); } return size; } int calculateSessionSizeThroughMap(HttpSession hs) { Enumeration keys = hs.getAttributeNames(); int size = -1; Map map = new HashMap(); int total = 0; int noSerializableSize = 0; while (keys.hasMoreElements()) { String key = (String) keys.nextElement(); Object value = hs.getAttribute(key); if (!(value instanceof Serializable)) { log(key + ", " + value.getClass().getName() + " is not serializable. "); //noSerializableSize += AnyObjectLength.getSize(value); continue; } map.put(key, value); } size = calculateObjectSize(map); size += noSerializableSize; return size; } int calculateSessionSizePerObject(HttpSession hs) { Enumeration keys = hs.getAttributeNames(); int size = 0; int total = 0; while (keys.hasMoreElements()) { String key = (String) keys.nextElement(); Object value = hs.getAttribute(key); if (!(value instanceof Serializable)) { log(key + ", " + value.getClass().getName() + " is not serializable. Getting closer size through reflection"); size = AnyObjectLength.getSize(value); } else { size = calculateObjectSize(value); } size += calculateObjectSize(key); total += size; } return total; } int calculateObjectSize(Object o) { if (!(o instanceof Serializable)) { log("calculateObjectSize: " + o.getClass().getName() + " is not serializable"); return -1; } ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); ObjectOutputStream objOut = null; int size = -1; try { objOut = new ObjectOutputStream(byteOut); objOut.writeObject(o); } catch (java.io.NotSerializableException ns) { log("| objeto " + o.getClass().getName() + " nao serializavel. Bypass"); //size = AnyObjectLength.getSize(o); } catch (IOException ex) { log(ex.getMessage()); } catch (RuntimeException re) { log(re.getMessage()); } catch (OutOfMemoryError oo) { log(oo.getMessage()); } finally { close(objOut); close(byteOut); size = byteOut.toByteArray().length; } return size; } void close(OutputStream out) { if (out != null) { try { out.close(); } catch (IOException ex) { log("Erro ao fechar outputstream: " + ex.getMessage()); } } } } class AnyObjectLength { public static int getSize(Object object) { int totalSize = 0; try { Field[] fields = object.getClass().getDeclaredFields(); for (int i = 0; i < fields.length; i++) { Field field = fields[i]; Class fieldClass = field.getType(); String className = fieldClass.getName(); int fieldSize = 0; if (!Modifier.isStatic(field.getModifiers())) { boolean accessFlag = field.isAccessible(); field.setAccessible(true); try { Object fieldValueObject = field.get(object); if (fieldValueObject == null) continue; if (className.equals("boolean")) { fieldSize = 1; } else if (fieldValueObject instanceof boolean[]) { fieldSize = ((boolean[])fieldValueObject).length; } else if (className.equals("char")) { fieldSize = 2; } else if (fieldValueObject instanceof char[]) { fieldSize = 2 * ((char[])fieldValueObject).length; } else if (className.equals("byte")) { fieldSize = 1; } else if (fieldValueObject instanceof byte[]) { fieldSize = 1 * ((byte[])fieldValueObject).length; } else if (className.equals("short")) { fieldSize = 2; } else if (fieldValueObject instanceof short[]) { fieldSize = 2 * ((short[])fieldValueObject).length; } else if (className.equals("int")) { fieldSize = 4; } else if (fieldValueObject instanceof int[]) { fieldSize = 4 * ((int[])fieldValueObject).length; } else if (className.equals("long")) { fieldSize = 8; } else if (fieldValueObject instanceof long[]) { fieldSize = 8 * ((long[])fieldValueObject).length; } else if (className.equals("float")) { fieldSize = 4; } else if (fieldValueObject instanceof float[]) { fieldSize = 4 * ((float[])fieldValueObject).length; } else if (className.equals("double")) { fieldSize = 8; } else if (fieldValueObject instanceof double[]) { fieldSize = 8 * ((double[])fieldValueObject).length; } else if (fieldValueObject instanceof Object[]) { Object[] objectArray = (Object[])fieldValueObject; for (int iObject = 0; iObject < objectArray.length; iObject++) { Object objectInArray = objectArray[iObject]; if (objectInArray != null) { int objectInArraySize = getSize(objectInArray); totalSize += objectInArraySize; // HttpSessionMetrics.log("Object: " + field.getName() + ", Type: " + className + ", Size: " + objectInArray); } } } else { int fieldValueObjectSize = getSize(fieldValueObject); totalSize += fieldValueObjectSize; // HttpSessionMetrics.log("Object: " + field.getName() + ", Type: " + className + ", Size: " + fieldSize); } } finally { field.setAccessible(accessFlag); } // HttpSessionMetrics.log("Field: " + field.getName() + ", Type: " + className + ", Size: " + fieldSize); } totalSize += fieldSize; } return totalSize; } catch(Exception e) { e.printStackTrace(); } return totalSize; } }