RFR: 8044107 Add Diagnostic Command to list all ClassLoaders

Staffan Larsen staffan.larsen at oracle.com
Tue Jun 3 06:39:21 UTC 2014


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   }



> 
>> 
>>> 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