Should optimizations be observable for JVMTI agents?

Reingruber, Richard richard.reingruber at sap.com
Tue Sep 24 21:45:53 UTC 2019


To get started: my own answers to the questions:

Optimizations should _not_ be observable for JVMTI agents. They should be as transparent as they are
for Java programs. Therefore EA should be disabled appropriately or JDK-8227745 should be realized
[3]

This is why:

Documentation states "[...] JVMTI [...] provides a way to inspect the state and to control the
execution of applications running in the JavaTM virtual machine (VM). " [1]

It clarifies again that it refers to the Java platform and not to the native platform. Eg '"monitor"
means Java programming language object monitor.' [2]

1. + 2.: No

In essence the JVMTI Doc says a JVMTI agent observes what the app itself observes. Namely the state
of the app. Optimizations that are transparent to the application must be transparent to JVMTI
agents also.

In other and more words: I see the JVM as an abstract model created by JLS/JVM specs. Concrete
implementations use the degrees of freedom the model has for optimizations to reduce resource
consumption for better performance. Optimizations are implementation details. They are transparent
to Java programs, as they don't have any additional effect on the application state in the
JVM(*). According to the documentation above JVMTI agents have to observe the very same state and
optimizations therefore are transparent for them too.

(*) should be true at least for compiler optimizations.

2a: No

So let's look at some thread T which has successfully completed a monitorenter bytecode on an object
O. The state of the program on the JVM is then T owns O's monitor.

It may be, though, that the monitorenter has no ordering effect, as specified by the Java memory
model, because no other thread S will ever execute a monitorenter on O. This allows to eliminate the
locking instructions, but even then O should be reported by GetOwnedMonitorInfo(), because that's
the state of the program on the JVM.

2b: No

This one is a little bit more complicated, because JLS 12.6.1 [4] states

"Optimizing transformations of a program can be designed that reduce the number of objects that are
reachable to be less than those which would naively be considered reachable. For example, a Java
compiler or code generator may choose to set a variable or parameter that will no longer be used to
null to cause the storage for such an object to be potentially reclaimable sooner.

Another example of this occurs if the values in an object's fields are stored in registers. The
program may then access the registers instead of the object, and never access the object again. This
would imply that the object is garbage. Note that this sort of optimization is only allowed if
references are on the stack, not stored in the heap."

This is tailored exactly to an optimization that aims to remove heap references as soon as possible
from the stack roots of the object graph in order to make them unreachable and reclaim their
memory. This change in reachability can be detected, though, by means of finalization and
java.lang.ref. Therefore it was "legalized" in the JLS.

The cited sections match scalar replacement very well also. Would have been nice and sufficient if
the statements were restricted to instances with finalization or subclasses of
java.lang.ref.Reference. They are considered to escape globally and are never scalar
replaced. Finalization and notification/nullification for java.lang.ref.Reference, though, are the
only means by which a Java program can observe the optimization. For other objects it is
impossible. Therefore scalar replacement is transparent to the Java app and consequently to JVMTI
agents also.

Note also that C2 can scalar replace objects even if they do escape globally (but only after
uncommon traps). Then 12.6.1 does not apply anyway.

2c: No. For the same reasons as for 2b.

2d: No, but not sure :)

JVMTI doc above says "... provides a way ... to control the execution of applications...". According
to this I would think a modification by a JVMTI agent should have an effect. There might be cases
(loop without call but with safepoint), where reads get cached, even without EA and modifications
have no effect.

Thanks, Richard.

[1] https://docs.oracle.com/en/java/javase/13/docs/specs/jvmti.html#whatIs

[2] https://docs.oracle.com/en/java/javase/13/docs/specs/jvmti.html#context

[3] JDK-8227745 in a nutshell will do what's already done when a thread traps from compiled
    execution to the interpreter: it reallocates and relocks objects upon access through JVMTI.
    This allows to enable EA and keep it transparent for agents.

[4] https://docs.oracle.com/javase/specs/jls/se13/html/jls-12.html#jls-12.6.1

-----Original Message-----
From: serviceability-dev <serviceability-dev-bounces at openjdk.java.net> On Behalf Of Reingruber, Richard
Sent: Dienstag, 24. September 2019 23:29
To: hotspot-compiler-dev at openjdk.java.net; serviceability-dev at openjdk.java.net
Subject: [CAUTION] Should optimizations be observable for JVMTI agents?

Hi,

I would like to get comments on the following questions:

  1. Should optimizations be observable for JVMTI agents in general?

  2. Should in particular optimzations based on escape analysis be observable?

     (a) Should GetOwnedMonitorInfo() exclude objects with eliminated locking?
         Currently it does [1]
     (b) Should GetLocalObject() return null for scalar replaced objects?
         Currently it does not. EA is disabled if agents can access locals.
     (c) Should scalar replaced objects be omitted when agents iterate the heap / traverse the
         object graph.
         Currently they are omitted [2]
     (d) Should memory optimizations (caching of reads) be observable?
         Eg. should field modifications of a NoEscape object O by a JVMTI agent have an effect in
         a compiled method that optimized field accesses based on EA?
         Currently memory optimizations can be observed, if the agent uses heap functions only to
         acquire a reference to the local object, which was not scalar replaced.

...and in the end hopefully an agreement :)

2a was discussed in the code review of JDK-8230677 [3]. David Holmes wished to generalize the
discussion and to draw more attention to it to get answers we can rely on.

Thanks, Richard.

[1] https://bugs.openjdk.java.net/browse/JDK-8230677

[2] https://bugs.openjdk.java.net/browse/JDK-8230956

[3] Prev. discussion
    https://mail.openjdk.java.net/pipermail/serviceability-dev/2019-September/029224.html


More information about the serviceability-dev mailing list