RFR: 8044107 Add Diagnostic Command to list all ClassLoaders
Mikael Gerdin
mikael.gerdin at oracle.com
Tue Jun 3 10:34:39 UTC 2014
On Tuesday 03 June 2014 08.39.21 Staffan Larsen wrote:
> On 2 jun 2014, at 09:28, Mikael Gerdin <mikael.gerdin at oracle.com> wrote:
> > 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?
>
> I have changed the hash function to:
>
> 103 static unsigned oop_hash(oop const& s1) {
> 104 unsigned hash = (unsigned)((uintptr_t)&s1);
> 105 return hash ^ (hash >> LogMinObjAlignment);
> 106 }
Great!
/Mikael
>
> >>> 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 did not think any of those were appropriate for my use.
>
> >> 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/
>
> even newer: http://cr.openjdk.java.net/~sla/8044107/webrev.02/
>
> Thanks,
> /Staffan
>
> > 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