RFR: 8248216: JFR: Unify handling of all OopStorage instances in LeakProfiler root processing

Erik Österlund erik.osterlund at oracle.com
Thu Jun 25 13:55:29 UTC 2020

Hi Markus,

Thanks for reviewing this.

On 2020-06-25 14:10, Markus Gronlund wrote:
> Hi Erik,
> If I understand this correctly, there exist some classification of the different OopStorages, maintained by OopStoragesSet? Where 'strong' is the class for "real" roots (non-weak), for example "JNI Global"?

Something like that.

> And it is the selected iterator that predicates which OopStorages you access, so using OopStorageSet::strong_iterator() delivers only the storages classified as roots? There are only two strong OopStorages at this point: "JNI Global" which I assume is for JNI Global Handles and "VM Global" which I don’t really know what it is, probably a VM internal equivalent of not using a Global JNI Handle? Looks like it's currently being used only by JVMTI?

Right. The reason I am proposing this patch is that this is about to 
change. Pretty much all global roots (non-thread roots) are moving into 
different OopStorages with appropriate names. So it won't be two for 
long. There will be only different OopStorages denoting the different 
root sets + thread roots + maybe CLDs depending on whether we fix them 
or not. To make the conversion easier, we are making code that visits 
the OopStorages automatic, so that adding more OopStorage objects is 
easier, without having to go through every single GC + leak profiler to 
update their root processing code to include yet another OopStorage and 
again do the same thing with that one that is done for all the other ones.

> Also a new Type is defined "_global_oop_handle" ? I assume this is what you get to access an oop in the "VM Global" OopStorage? If so, this is not accessible to the end user.

Right. These things used to be stray oops in the C++ code, reachable 
through oops_do functions. Now they are being moved to OopStorage 
instances and are accessed through global handles, very similar to JNI 
handles, but are not part of JNI. And like all those roots, they are 
indeed not accessible to the end user (unless you count heap traversal 

> Implementation looks reasonable, but for Leak Profiler, I am a bit concerned that users will get too much internals, detailing the VM's view of the world, not necessarily what the user expects and can work with at their level of abstraction. We already have a bit much of that already (Type: "_handle_area" and several internal subsystems, for example).

I am not exposing any information that is not already exposed. You 
already have a set of roots and give them names (including the today 2 
OopStorage objects). All I changed is so the OopStorage roots get their 
human readable names from their OopStorage instead, which defines such a 
human readable name. And these are not internal names for us, they are 
meant to be user facing, and will be consistent with what you see in GC 
log output, etc, so that users can match them in a consistent way. If 
the human readable names defined for our OopStorage objects are bad, 
then it sounds like what you really want is to change their name strings 
(defined in oopStorageSet.cpp).

> Leak Profiler will have a dependency on the internal names defined for the different OopStorages, which are no longer opaque but will be exposed externally. And this exposure can be stronger than a "debug" message, which is again VM internal, but it could potentially be tied to an API.

Again, the names I print are not internal names, they are strings that 
have been selected as user facing, just like the strings you had defined 
in JFR before. The difference is only in the exact name string chosen, 
but they are both supposed to be human readable. And now they can also 
be consistent.

Having said that, I have strong reservations about tying any root set 
name to an API. JVMTI does that and it is a nightmare.

1) The set of VM roots are constantly changing, and any code relying on 
HotSpot having the same set of roots, set in stone, is bound to break. 
For example, I am about to remove the ObjectMonitor roots, because they 
will simply not be strong roots any more. Anyone expecting them to be 
around will fail. A whole subsystem could move its roots out to Java for 
whatever reason. We can't know how roots will change, only that they 
definitely can and will change. The root sets of HotSpot are and always 
will be, an internal implementation detail of our JVM.

2) Even if you still want to tie root sets to an API, this should not be 
done with human readable strings that you are not allowed to alter. It 
should be done with some kind of enumeration or something, that is meant 
for code and not humans. JVMTI root sets do this, and I still think it 
really should not be done as explained above.


> Thanks
> Markus
> -----Original Message-----
> From: Erik Österlund
> Sent: den 24 juni 2020 15:29
> To: Stefan Karlsson <stefan.karlsson at oracle.com>; Hotspot dev runtime <hotspot-runtime-dev at openjdk.java.net>
> Cc: Markus Gronlund <markus.gronlund at oracle.com>
> Subject: Re: RFR: 8248216: JFR: Unify handling of all OopStorage instances in LeakProfiler root processing
> Hi Stefan,
> Thanks for the review.
> Updated to use your new API:
> http://cr.openjdk.java.net/~eosterlund/8248216/webrev.01/
> Also added Markus to the conversation.
> Thanks,
> /Erik
> On 2020-06-24 14:36, Stefan Karlsson wrote:
>> Hi Erik,
>> On 2020-06-24 11:13, Erik Österlund wrote:
>>> Hi,
>>> We want it to be as convenient as possible for the runtime to add new
>>> OopStorage instances. Therefore, rather than picking specific
>>> OopStorages during LeakProfiler root processing, the
>>> OopStorageSet::strong_iterator() should be used instead. That way,
>>> once a new OopStorage is added to the OopStorageSet, it is
>>> automatically plugged in to the JFR LeakProfiler.
>>> Bug:
>>> https://bugs.openjdk.java.net/browse/JDK-8248216
>>> Webrev:
>>> http://cr.openjdk.java.net/~eosterlund/8248216/webrev.00/
>> https://cr.openjdk.java.net/~eosterlund/8248216/webrev.00/src/hotspot/
>> share/jfr/leakprofiler/chains/rootSetClosure.cpp.udiff.html
>> I've now pushed a change so that you can simplify:
>> + for (OopStorageSet::Iterator it = OopStorageSet::strong_iterator();
>> !it.is_end(); ++it) {
>> + it->oops_do(this);
>> + } to: OopStorageSet::strong_oops_do(this); The rest looks fine, but
>> should maybe be reviewed on hotspot-jfr-dev. Thanks, StefanK
>>> Thanks,
>>> /Erik

More information about the hotspot-runtime-dev mailing list