I found this thing called heapprofile, some 100 lines of C++ code that connect to the Java Native Profiler Interface and provide a hook to dump the heap without imposing any substantial overhead to the JVM, this is a *very* useful and lightweight tool.
You can find the source code here:
http://www.virtualmachine.de/heapprofile/heapprofile.cpp
Here is the result I got (macosx jdk 1.4.1):
$ c servlet
when jetty starts, before making an HTTP request type:
CTRL-\ -> creates the 'heap.dump' file in CWD
then
$ cut -d ' ' -f 2 < heap.dump | sort -n | uniq -c | sort -n | tail -30
86 java.util.jar.JarFile$JarFileEntry 102 [C 108 java.lang.Package 112 org.apache.cocoon.util.log.ExtensiblePatternFormatter$PatternRun 118 org.mortbay.util.StringMap$Node 122 org.apache.xerces.xni.QName 143 java.lang.ref.Finalizer 155 org.apache.excalibur.instrument.CounterInstrument 160 java.lang.reflect.Constructor 162 java.lang.ref.SoftReference 170 java.util.Vector 179 java.net.URL 220 java.util.Hashtable 247 org.apache.avalon.framework.configuration.DefaultConfiguration 256 org.apache.commons.collections.StaticBucketMap$Lock 305 java.util.ArrayList 393 java.util.jar.Attributes 487 java.lang.Class 583 java.lang.Object 594 java.util.HashMap 719 java.util.Hashtable$Entry 1199 java.util.jar.Attributes$Name 1746 [8 2400 [10 2632 [9 2701 org.apache.excalibur.store.impl.JispStringKey 2927 java.util.HashMap$Entry 7066 java.lang.String 16380 [5 20818 org.apache.avalon.excalibur.collections.BucketMap$Node
then I send *one* request page to http://localhost:8888 and I get:
137 org.mortbay.util.StringMap$Node 139 sun.reflect.DelegatingConstructorAccessorImpl 141 java.lang.Package 148 java.lang.ref.Finalizer 162 org.apache.avalon.excalibur.component.DefaultComponentFactory 181 java.net.URL 215 java.util.Vector 216 org.apache.avalon.excalibur.collections.BucketMap 236 java.util.Hashtable 238 org.apache.excalibur.instrument.ValueInstrument 246 java.lang.ref.SoftReference 256 org.apache.commons.collections.StaticBucketMap$Lock 298 java.lang.reflect.Constructor 367 org.apache.avalon.framework.configuration.DefaultConfiguration 397 java.util.jar.Attributes 514 org.apache.excalibur.instrument.CounterInstrument 602 java.util.ArrayList 732 java.lang.Class 797 java.util.HashMap 1044 java.lang.Object 1212 java.util.Hashtable$Entry 1221 java.util.jar.Attributes$Name 2495 [8 2701 org.apache.excalibur.store.impl.JispStringKey 4225 java.util.HashMap$Entry 4797 [9 4876 [10 8079 java.lang.String 21515 [5 53225 org.apache.avalon.excalibur.collections.BucketMap$Node
then I hit the same page 10 times:
137 org.mortbay.util.StringMap$Node 139 sun.reflect.DelegatingConstructorAccessorImpl 141 java.lang.Package 147 java.lang.ref.Finalizer 162 org.apache.avalon.excalibur.component.DefaultComponentFactory 181 java.net.URL 216 org.apache.avalon.excalibur.collections.BucketMap 221 java.util.Vector 238 org.apache.excalibur.instrument.ValueInstrument 239 java.util.Hashtable 256 org.apache.commons.collections.StaticBucketMap$Lock 259 java.lang.ref.SoftReference 304 java.lang.reflect.Constructor 367 org.apache.avalon.framework.configuration.DefaultConfiguration 397 java.util.jar.Attributes 514 org.apache.excalibur.instrument.CounterInstrument 603 java.util.ArrayList 739 java.lang.Class 803 java.util.HashMap 1052 java.lang.Object 1221 java.util.jar.Attributes$Name 1228 java.util.Hashtable$Entry 2504 [8 2701 org.apache.excalibur.store.impl.JispStringKey 3156 [10 4242 java.util.HashMap$Entry 4801 [9 8298 java.lang.String 21822 [5 53967 org.apache.avalon.excalibur.collections.BucketMap$Node
These numbers represent the total object count per type.
On the other hand, the following:
$ sort -n heap.dump | tail -30
8208 [8 8208 [8 8208 [8 8208 [8 8208 [8 8856 [8 9744 [10 10816 com.coyotegulch.jisp.KeyObject 10896 [5 11600 [5 11632 [10 12808 [8 14960 [5 15624 [5 16400 [5 16400 [5 16616 [10 17160 [5 17280 [5 17584 [5 17648 [5 18328 [5 21616 [11 21624 [11 23704 [5 35720 [8 65552 [8 65552 [8 117904 [10 262168 [10
represent the list of the biggest 30 objects in the JVM.
I assume, but I'm not sure, that [xx are native internal objects, so there is not much we can do about those. Still, I would like to know what is that [10 object that accounts for so much memory.
I'm currently experimenting with other profilers so expect more data soon.
Stefano.