RFR: 8044107 Add Diagnostic Command to list all ClassLoaders

Mikael Gerdin mikael.gerdin at oracle.com
Mon Jun 2 07:28:07 UTC 2014


On Friday 30 May 2014 11.40.54 Staffan Larsen wrote:
> On 30 maj 2014, at 10:49, Mikael Gerdin <mikael.gerdin at oracle.com> wrote:
> > Hi Staffan,
> > 
> > On Wednesday 28 May 2014 16.50.28 Staffan Larsen wrote:
> >> This change adds a new Diagnostic Command to list all ClassLoaders and
> >> some
> >> statistics for each classloader. The command is called
> >> “GC.classloader_stats” and the information listed is:
> >> 
> >> * An id for the ClassLoader. This is the pointer to the Klass of the
> >> ClassLoader. The reason for using the Klass* (instead of the oop) is that
> >> it is stable across invocations. * The id of the ClassLoader’s parent
> >> ClassLoader.
> >> * The pointer to the ClassLoaderData structure in the VM. This can be
> >> useful for debugging. * The number of classes loaded by the ClassLoader.
> >> * The total size of all allocated metaspace chunks for the ClassLoader.
> >> * The total size of all allocated metaspace blocks for the ClassLoader.
> >> 
> >> If there are anonymous classes (invokedynamic classes) attributed to the
> >> ClassLoader, the following additional information is listed: * The number
> >> of anonymous classes loaded by the ClassLoader.
> >> * The total size of all allocated metaspace chunks for anonymous classes
> >> in
> >> the ClassLoader. * The total size of all allocated metaspace blocks for
> >> anonymous classes in the ClassLoader.
> >> 
> >> The information is gathered during a safe point to guarantee that the
> >> data
> >> structures are consistent.
> >> 
> >> I have added a small test and have run this through jprt. A CCC request
> >> has
> >> been filed.
> >> 
> >> webrev: http://cr.openjdk.java.net/~sla/8044107/webrev.00/
> >> bug: https://bugs.openjdk.java.net/browse/JDK-8044107
> > 
> > I'm going to leave the naming of the anonymous classes and dig into the
> > code a bit:
> > 
> > in classLoaderStats.hpp:
> > 
> > Use the (at runtime) known object alignment?
> > 105     return hash ^ (hash >> 3); // just in case we're dealing with
> > aligned ptrs
> 
> I just copied code from resourceHash.hpp… What would you suggest?

oops can have a larger alignment than 3, since you know that you will always 
have oops as the hash key, why not use that knowledge and shift them down the 
appropriate amount?

> 
> > The &-operator is not needed here:
> > 108   typedef ResourceHashtable<oop, ClassLoaderStats*,
> > 109       &ClassLoaderStatsClosure::oop_hash,
> > &ClassLoaderStatsClosure::oop_equals> StatsTable;
> 
> Removed.
> 
> > do_entry does not need to be virtual since the template instantiation
> > binds to the symbol during compilation
> > 129   virtual bool do_entry(oop const& key, ClassLoaderStats* const& cls);
> 
> I want to override it in a closed source class, so I’ll keep it as virtual.

Ok.

> 
> > in classLoaderStats.cpp:
> > 
> > Every time you encounter a CLD which reports a ClassLoader oop you will
> > overwrite the _cld field of the ClassLoaderStats.
> > 
> >  59   cls->_cld = cld;
> > 
> > I'm not sure if this was your intention or not, but you are relying on the
> > subtle fact that since CLD:s are prepended to the linked list in CLDG the
> > _cld field will end up pointing to the ClassLoader's CLD instead of any
> > of the anonymous classes which also hash to the same ClassLoder oop but
> > have different CLDs.
> 
> Good catch. The code should be:
> 
>   if (!cld->is_anonymous()) {
>     cls->_cld = cld;
>   }
> 
> > Can you convert this to an if()-block or add parenthesis for clarity?
> > 
> >  60   cls->_classloader = cl == NULL ? NULL : cl->klass();
> 
> Added parenthesis.

Thanks.

> 
> > The ResourceMark here is unnecessary, all the resource allocations done by
> > the ClassLoaderStats-classes are done by the VMThread and are in the
> > scope of a ResourceMark covering the call to VM_Operation::doit()
> > 165   ResourceMark rm;
> 
> I wasn’t aware that doit() was already covered. Removed.
> 
> > in ClassLoaderStatsTest.java:
> > There is at least one other variant of "DummyClassLoader" in the
> > testlibrary, can you see if any of them are reusable?
> 
> I could not find one that did what I wanted. Which one are you referring to?

I was thinking about 
test/testlibrary/com/oracle/java/testlibrary/ByteCodeLoader.java

or, perhaps to a lesser extent
test/runtime/testlibrary/ClassUnloadCommon.java

It just seems like creating a class loader in order to load a specific class 
is something that is not entirely uncommon in our testing. If you don't see a 
good opportunity for making this into a reusable component for other tests 
then that's fine too.

> 
> I also changed the name of the diagnostic command from
> “GC.classloader_stats” to “VM.classloader_stats” and the output of
> anonymous classes to "+ unsafe anonymous classes”.

Ok.

> 
> new webrev: http://cr.openjdk.java.net/~sla/8044107/webrev.01/

Looks good.

/Mikael

> 
> Thanks,
> /Staffan
> 
> > /Mikael
> > 
> >> Example output:
> >> 
> >> ClassLoader         Parent              CLData*            Classes  
> >> ChunkSz>> 
> >>  BlockSz  Type 0x00000007c002d908  0x0000000000000000  0x0000000000000000
> >>  
> >>     0         0         0  sun.misc.Launcher$ExtClassLoader
> >> 
> >> 0x0000000000000000  0x0000000000000000  0x00007fb239c08de0     761
> >> 4694016   4241312  <boot classloader> 37     75776     50928   +
> >> invokedynamic classes 0x00000007c0061028  0x00000007c0036878
> >> 0x00007fb239c2de60       1      6144      1976
> >> ClassLoaderStatsTest$DummyClassLoader 1      2048      1288   +
> >> invokedynamic classes 0x00000007c0036878  0x00000007c002d908
> >> 0x00007fb239e10fc0       8     88064     31544
> >> sun.misc.Launcher$AppClassLoader Total = 4
> >> 
> >>                    808   4866048   4327048 ChunkSz: Total size of all
> >> 
> >> allocated metaspace chunks
> >> BlockSz: Total size of all allocated metaspace blocks (each chunk has
> >> several blocks)
> >> 
> >> 
> >> Thanks,
> >> /Staffan



More information about the hotspot-dev mailing list