JDK-8275775 : Add jcmd VM.classes to print details of all classes
  • Type: Enhancement
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 18
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2021-10-22
  • Updated: 2024-03-04
  • Resolved: 2022-03-08
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 19
19 b13Fixed
Related Reports
Relates :  
Relates :  
Description
Add VM.classes to print details of all classes, output looks like:

1. jcmd VM.classes
KlassAddr           Size  State     Flags    LoaderName    ClassName
0x0000000800c0b400  62    inited    W        bootstrap     java.lang.invoke.LambdaForm$MH/0x0000000800c0b400  
0x0000000800c0b000  62    inited    W        bootstrap     java.lang.invoke.LambdaForm$DMH/0x0000000800c0b000  
0x0000000800c0ac00  62    inited    W        bootstrap     java.lang.invoke.LambdaForm$MH/0x0000000800c0ac00  
...

2. jcmd VM.classes verbose
KlassAddr           Size  State     Flags    LoaderName    ClassName
0x0000000800c0b400  62    inited    W        bootstrap     java.lang.invoke.LambdaForm$MH/0x0000000800c0b400  
java.lang.invoke.LambdaForm$MH/0x0000000800c0b400 {0x0000000800c0b400}
 - instance size:     2
 - klass size:        62
 - access:            final synchronized 
 - state:             inited
 - name:              'java/lang/invoke/LambdaForm$MH+0x0000000800c0b400'
 - super:             'java/lang/Object'
 - sub:               
 - arrays:            NULL
 - methods:           Array<T>(0x00007f620841f210)
 - method ordering:   Array<T>(0x0000000800a7e5a8)
 - default_methods:   Array<T>(0x0000000000000000)
 - local interfaces:  Array<T>(0x00000008005af748)
 - trans. interfaces: Array<T>(0x00000008005af748)
 - constants:         constant pool [41] {0x00007f620841f030} for 'java/lang/invoke/LambdaForm$MH+0x0000000800c0b400' cache=0x00007f620841f380
 - class loader data:  loader data: 0x00007f61c804a690 of 'bootstrap' has a class holder
 - source file:       'LambdaForm$MH'
 - class annotations:       Array<T>(0x0000000000000000)
 - class type annotations:  Array<T>(0x0000000000000000)
 - field annotations:       Array<T>(0x0000000000000000)
 - field type annotations:  Array<T>(0x0000000000000000)
 - inner classes:     Array<T>(0x00000008005af6d8)
 - nest members:     Array<T>(0x00000008005af6d8)
 - permitted subclasses:     Array<T>(0x00000008005af6d8)
 - java mirror:       a 'java/lang/Class'{0x000000011f4b3968} = 'java/lang/invoke/LambdaForm$MH+0x0000000800c0b400'
 - vtable length      5  (start addr: 0x0000000800c0b5b8)
 - itable length      2 (start addr: 0x0000000800c0b5e0)
 - ---- static fields (1 words):
 - static final '_D_0' 'Ljava/lang/invoke/LambdaForm;' @112 
 - ---- non-static fields (0 words):
 - non-static oop maps: 
0x0000000800c0b000  62    inited    W        bootstrap     java.lang.invoke.LambdaForm$DMH/0x0000000800c0b000  
java.lang.invoke.LambdaForm$DMH/0x0000000800c0b000 {0x0000000800c0b000}
 - instance size:     2
 - klass size:        62
 - access:            final synchronized 
 - state:             inited
 - name:              'java/lang/invoke/LambdaForm$DMH+0x0000000800c0b000'
 - super:             'java/lang/Object'
 - sub:               
 - arrays:            NULL
 - methods:           Array<T>(0x00007f620841ea68)
 - method ordering:   Array<T>(0x0000000800a7e5a8)
 - default_methods:   Array<T>(0x0000000000000000)
 - local interfaces:  Array<T>(0x00000008005af748)
 - trans. interfaces: Array<T>(0x00000008005af748)
 - constants:         constant pool [49] {0x00007f620841e838} for 'java/lang/invoke/LambdaForm$DMH+0x0000000800c0b000' cache=0x00007f620841ebe0
 - class loader data:  loader data: 0x00007f61c804a750 of 'bootstrap' has a class holder
 - source file:       'LambdaForm$DMH'
 - class annotations:       Array<T>(0x0000000000000000)
 - class type annotations:  Array<T>(0x0000000000000000)
 - field annotations:       Array<T>(0x0000000000000000)
 - field type annotations:  Array<T>(0x0000000000000000)
 - inner classes:     Array<T>(0x00000008005af6d8)
 - nest members:     Array<T>(0x00000008005af6d8)
 - permitted subclasses:     Array<T>(0x00000008005af6d8)
 - java mirror:       a 'java/lang/Class'{0x000000011f4b0968} = 'java/lang/invoke/LambdaForm$DMH+0x0000000800c0b000'
 - vtable length      5  (start addr: 0x0000000800c0b1b8)
 - itable length      2 (start addr: 0x0000000800c0b1e0)
 - ---- static fields (1 words):
 - static final '_D_0' 'Ljava/lang/invoke/LambdaForm;' @112 
 - ---- non-static fields (0 words):
...

Comments
Changeset: 3f0684d0 Author: Yi Yang <yyang@openjdk.org> Date: 2022-03-08 03:14:21 +0000 URL: https://git.openjdk.java.net/jdk/commit/3f0684d0b85662724af845a4ee6b97d9c5ceacbd
08-03-2022

A pull request was submitted for review. URL: https://git.openjdk.java.net/jdk/pull/7105 Date: 2022-01-17 09:31:54 +0000
17-01-2022

In light of the comments in the PR above, can you change the name and description of this issue? I think having VM.classes is not a bad idea to print more information about each of the loaded classes. I have my own version of this that prints the sizes of the instanceKlass (so that I know how big the vtables are). +class KlassDCmdClosure : public LockedClassesDo { + outputStream* _st; +public: + KlassDCmdClosure(outputStream* st) : _st(st) {} + + void do_klass(Klass* k) { + _st->print_cr("Class %s size %d", k->external_name(), k->size() * wordSize); + } +}; My preference is for a minimal command that does one thing: for each class, show sizes of the class, whether it's finalized, maybe some other interesting attributes. All with one line per class. As far as having a CSR to add a command, I personally don't see it as necessary. I don't know how much publicity that generates for your new command. That said, I filed a CSR for deleting a jcmd once, in the unlikely case someone might be using it.
10-01-2022