001package org.nuxeo.runtime.javaagent; 002 003import java.lang.instrument.Instrumentation; 004import java.lang.reflect.Array; 005import java.lang.reflect.Field; 006import java.lang.reflect.Modifier; 007import java.security.AccessController; 008import java.security.PrivilegedAction; 009import java.util.IdentityHashMap; 010import java.util.Map; 011 012public class NuxeoAgent { 013 014 protected static NuxeoAgent agent = new NuxeoAgent(); 015 016 protected Instrumentation instrumentation; 017 018 public static void premain(String args, Instrumentation inst) { 019 agent.instrumentation = inst; 020 } 021 022 public static void agentmain(String args, Instrumentation inst) { 023 agent.instrumentation = inst; 024 } 025 026 public long sizeOf(final Object o) { 027 return instrumentation.getObjectSize(o); 028 } 029 030 public long deepSizeOf(final Object o) { 031 if (o == null) { 032 throw new NullPointerException(); 033 } 034 035 return AccessController.doPrivileged(new PrivilegedAction<Long>() { 036 @Override 037 public Long run() { 038 return new GraphSizeProfiler().visit(o); 039 } 040 }); 041 } 042 043 protected class GraphSizeProfiler { 044 045 protected final Map<Object, Object> visited = new IdentityHashMap<Object, Object>(); 046 047 protected long visit(Object each) { 048 if (each == null) { 049 return 0; 050 } 051 if (visited.containsKey(each)) { 052 return 0; 053 } 054 visited.put(each, each); 055 long size = instrumentation.getObjectSize(each); 056 Class<?> eachType = each.getClass(); 057 if (eachType.isArray()) { 058 if (eachType.getComponentType().isPrimitive()) { 059 return 0; 060 } 061 for (int i = 0; i < Array.getLength(each); i++) { 062 size += visit(Array.get(each, i)); 063 } 064 } else { 065 size += visit(each, eachType); 066 } 067 return size; 068 } 069 070 protected long visit(Object each, Class<?> eachType) { 071 if (eachType.equals(Object.class)) { 072 return 0; 073 } 074 long size = 0; 075 for (Field eachField : eachType.getDeclaredFields()) { 076 size += visit(each, eachField); 077 } 078 return size + visit(each, eachType.getSuperclass()); 079 } 080 081 protected long visit(Object each, Field eachField) { 082 if ((eachField.getModifiers() & Modifier.STATIC) != 0) { 083 return 0; 084 } 085 if (eachField.getType().isPrimitive()) { 086 return 0; 087 } 088 boolean oldAccessible = eachField.isAccessible(); 089 eachField.setAccessible(true); 090 try { 091 return visit(eachField.get(each)); 092 } catch (Exception e) { 093 throw new RuntimeException("Exception trying to access field " + eachField, e); 094 } finally { 095 eachField.setAccessible(oldAccessible); 096 } 097 } 098 } 099 100}