RFR(s): 8203682: Add jcmd "VM.classloaders" command to print out class loader hierarchy, details
Thomas Stüfe
thomas.stuefe at gmail.com
Tue Jun 5 17:43:05 UTC 2018
I did like Kirk's proposal, which mirrors Coleen's proposal about
printing the address and also is consistent with how
VM.system_dictionary prints the loader instance.
I changed my change accordingly (in-place, since I did not want to
confuse reviewers).
The output looks like this:
+--
org.springframework.boot.devtools.restart.classloader.RestartClassLoader
{0x00000007065adba8}
| |
| | Classes: hello.Application
| | hello.GreetingController
| |
hello.Application$$EnhancerBySpringCGLIB$$6738b31f
| | com.sun.proxy.$Proxy49
| |
org.springframework.boot.autoconfigure.http.HttpMessageConverters$$EnhancerBySpringCGLIB$$1d90bff9
| |
org.springframework.boot.autoconfigure.http.HttpMessageConverters$$FastClassBySpringCGLIB$$d5af8918
| |
org.springframework.boot.autoconfigure.http.HttpMessageConverters$$EnhancerBySpringCGLIB$$1d90bff9$$FastClassBySpringCGLIB$$8fc601a2
| | (7 classes)
| |
| +--
org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader
{0x000000070f900e40}
| |
| +-- jdk.internal.reflect.DelegatingClassLoader
{0x000000070f9004c0}
|
| Classes:
jdk.internal.reflect.GeneratedSerializationConstructorAccessor4
| (1 class)
so, class loader instance address now is printed unconditionally and
trails the name/class of the loader.
For reviewing, the current webrevs remain:
Full: http://cr.openjdk.java.net/~stuefe/webrevs/8203682-jcmd-print-classloader-hierarchy/webrev.01/webrev/
Delta: http://cr.openjdk.java.net/~stuefe/webrevs/8203682-jcmd-print-classloader-hierarchy/webrev.00-to-01/webrev/
Thanks a lot,
Thomas
On Mon, Jun 4, 2018 at 8:56 PM, Kirk Pepperdine
<kirk.pepperdine at gmail.com> wrote:
>
>>
>>> I don't like the use of mtInternal, but there doesn't seem to be a better
>>> category (or one to add).
>>
>> The point is moot now since I followed your suggestion below, using
>> resource area instead.
>>
>>>
>>> 152 if (_loader_oop != NULL) {
>>> 153 loader_klass = _loader_oop->klass();
>>> 154 if (loader_klass != NULL) {
>>> 155 loader_class_name = loader_klass->external_name();
>>> 156 }
>>> 157 oop nameOop = java_lang_ClassLoader::name(_loader_oop);
>>> 158 if (nameOop != NULL) {
>>> 159 const char* s = java_lang_String::as_utf8_string(nameOop);
>>> 160 if (s != NULL) {
>>> 161 loader_name = s;
>>> 162 }
>>> 163 }
>>>
>>> These are available to the ClassLoaderData (_cld) as class_loader_name() and
>>> class_loader_klass(). I would rather see ClassLoaderData::loader_name()
>>> used - once fixed. Also, I don't like <unnamed> in the output. It seems
>>> that most class loaders will be unnamed, so the output will be too noisy
>>> with that. Also, there's an unnamed module so that makes it very confusing.
>>
>> Okay to all of that. I changed the coding to use
>> class_loader_{klass|name} consistently and only print out loader names
>> when set:
>>
>> 24942:
>> +-- <bootstrap>
>> |
>> +-- "platform", instance of
>> jdk.internal.loader.ClassLoaders$PlatformClassLoader
>> |
>> +-- "app", instance of
>> jdk.internal.loader.ClassLoaders$AppClassLoader
>> |
>> +--
>> test3.internals.InMemoryJavaFileManager$InMemoryClassLoader
>>
>>
>> See more examples:
>> http://cr.openjdk.java.net/~stuefe/webrevs/8203682-jcmd-print-classloader-hierarchy/out2.txt
>> http://cr.openjdk.java.net/~stuefe/webrevs/8203682-jcmd-print-classloader-hierarchy/out3.txt
>>
>>>
>>> Since this is in a safepoint, maybe you can add a ResourceMark at 472,
>>> remove it from 362 and make all classes ResourceObj allocated. Then you can
>>> remove the code to delete the types.
>>>
>>
>> I originally did not do it since I did not know whether
>> ClassLoaderDataGraph::cld_do() would use resource marks. But it does
>> not, and you are right, this makes the coding simpler.
>>
>>> Can you add assert that you are at a safepoint at the beginning of this, so
>>> you don't have to worry about LoaderTreeNode::_loader_oop getting collected.
>>
>> Done. (only in full webrev, sorry, I messed up the delta)
>>
>>> It seems that by saving _cld in LoaderTreeNode, that you don't need
>>> _loader_oop.
>>
>> Unfortunately not. To add a node to the tree, I need its parent node.
>> At that time I may not yet have encountered the parent loader CLD. So
>> I add the parent node, and mark it with the parent loader oop. Later,
>> when I encounter the CLD for the parent, I complete the node.
>> I added a comment to make that clearer.
>>
>>>
>>> This code looks like it's walking the CLDG in order to make a different
>>> Class loader graph for printing. Is it necessary to show the hierarchy
>>> information?
>>>
>>
>> It proved useful in the classic delegation scenarios.
>>
>>> It seems like printing the address is better than <unnamed>, which is what
>>> I've looked at with the system dictionary logging.
>>>
>>
>> Oh, I do that, when option "verbose" is given:
>>
>> +-- <bootstrap>
>> |
>> | Loader Data: 0x00007fc458239040
>> | Loader Klass: 0x0000000000000000
>> | Loader Oop: 0x0000000000000000
>> |
>> +-- "platform", instance of
>> jdk.internal.loader.ClassLoaders$PlatformClassLoader
>> |
>> | Loader Data: 0x00007fc4583f7350
>> | Loader Klass: 0x00000008000107b0
>> | Loader Oop: 0x000000060d077b90
>> |
>> +-- "app", instance of
>> jdk.internal.loader.ClassLoaders$AppClassLoader
>> |
>> | Loader Data: 0x00007fc4583eb740
>> | Loader Klass: 0x0000000800010348
>> | Loader Oop: 0x000000060d079b30
>> |
>>
>> I wondered whether I should print the loader oop more prominently, and
>> always. Should I? For example:
>>
>> +-- {0x000000060d077b90} "platform", instance of
>> jdk.internal.loader.ClassLoaders$PlatformClassLoader
>> |
>> | Loader Data: 0x00007fc4583f7350
>> | Loader Klass: 0x00000008000107b0
>> |
>> +-- {0x000000060d079b30} "app", instance of
>> jdk.internal.loader.ClassLoaders$AppClassLoader
>> |
>> | Loader Data: 0x00007fc4583eb740
>> | Loader Klass: 0x0000000800010348
>
> I can bike shed here…
>
> “platform”,jdk.internal.loader.ClassLoaders$PlatformClassLoader{0x000000060d077b90}
> |
> | Loader Data: 0x00007fc4583f7350
> | Loader Klass: 0x00000008000107b0
> |
> +-- "app",jdk.internal.loader.ClassLoaders$AppClassLoader{0x000000060d079b30}
> |
> | Loader Data: 0x00007fc4583eb740
> | Loader Klass: 0x0000000800010348
>
> Kind regards,
> Kirk
>
More information about the hotspot-runtime-dev
mailing list