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