JDK-8172261 : [JVMTI] Specification for early VM start event needs to lower expectations in relation to class loading
  • Type: Bug
  • Component: hotspot
  • Sub-Component: jvmti
  • Affected Version: 9
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2017-01-05
  • Updated: 2017-05-17
  • Resolved: 2017-01-19
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 10 JDK 9
10Fixed 9 b156Fixed
Related Reports
CSR :  
Relates :  
Relates :  
Relates :  
Description
The JVM TI VMStart event has always been somewhat naively over-optimistic in what is allowed once the "start phase" has been entered:

" At this time JNI is live but the VM is not yet fully initialized. Once this event is generated, the agent is free to call any JNI function."

This suggests that any JNI function can be called, even if the VM is not yet fully initialized, which is simply not a practical reality in current JVM implementations. In particular, loading and/or initializing classes before the core platform classes have been initialized is rarely possible and can easily crash the VM.

In JDK-8142968, with the introduction of the Module system, it was recognized that things would be even more problematic if class loading was attempted before the module system was initialized, and the concept of the "early VM start event" was introduced. This event is triggered at the same early point in VM initialization as before, but only if the can_generate_early_vmstart capability is held. Otherwise the VM start event is delayed until after the module system (and numerous other parts of the VM) has been initialized.

The updated VMStart specification described this and tried to clarify what was possible during the "early VM start":

"The timing of this event may depend on whether the agent has added the can_generate_early_vmstart capability or not. If the capability has been added then the VM posts the event as early as possible. The VM is capable of executing bytecode but it may not have initialized to the point where it can load classes in modules other than java.base. Agents that do load-time instrumentation in this phase must take great care when instrumenting code that potentially executes in this phase. Care should also be taken with JNI FindClass as it may not be possible to load classes that are not in the java.base module. If the capability has not been added then the VM delays posting this event until it is capable of loading classes in modules other than java.base or the VM has completed its initialization."

Unfortunately this is still overly-optimistic as even classes in the base module may not be successfully loaded and/or initialized at the early VM start time.

Given we have introduced this notion of an early VM start event, it seems appropriate to lower the expectations as to what may and may not be achievable at this time. Specifically that any attempt at class loading, or initialization, may fail, even to the extent of triggering a JVM crash.
Comments
The proposed wording looks mostly okay but maybe: "where it can load classes" -> "where it can load classes in modules other than java.base or even arbitrary classes in java.base" "... to load classes and attempts to do so could result in abrupt termination of the VM" -> "to load arbitrary classes. Attempts to so may result in unpredictable behavior, maybe even stability issues on some VM implementations".
16-01-2017

[@dholmes] It looks great. Added myself as a reviewer.
16-01-2017

Alan: your suggested changes seem okay. I will use them for CCC version. Thanks.
16-01-2017

The limitations as to what can be done in the start phase were never fully detailed in the spec. As the spec is VM agnostics then it would be hard to do anyway. So the issue raised in this bug is actually a long standing issue, we just got lucky in older releases because there probably aren't too many tests or real-world agents trying to load and execute arbitrary code in the start phase. The reason for the can_generate_early_vmstart capability is to address the somewhat niche need of agents that need events during early VM startup. The alternative proposal was of course to introduce a new event or JVM TI phase but that adds complexity and is problematic to get working with existing agents. If there are agents that really want to split the start phase then emulate it by creating two JVM TI environments and enable the can_generate_early_vmstart capability in one but not the other.
11-01-2017

One concern or question. Use of the JNI FindClass is safe after the normal (non-early) VMStart event is posted . But after the early VMStart is posted, the earliest point to use the FindClass is the VMInit event. So that the interval between (unposted) normal VMStart event and VMInit event becomes unsafe for JNI FindClass if the can_generate_early_vmstart capability was requested. It is because the agent is not notified about the normal VMStart point in such a case. As a result with the early VMStart the agents get more events but they are unsafe to use the JNI FindClass until the VMInit event is posted.
11-01-2017

Thanks, Alan. I kind of expected this kind of explanation as you already had some brief email discussion on this topic. Still, it is good to have it spelled in this bug report. I know about this "strange" solution with two JVM TI environments. It should be Ok because, as you said, very rare agents needs event during early VM startup.
11-01-2017

Suggested changes: Replace: The VM is capable of executing bytecode but it may not have initialized to the point where it can load classes in modules other than java.base. with: The VM is capable of executing bytecode but it may not have initialized to the point where it can load classes, even those in the java.base module. Replace: Care should also be taken with JNI FindClass as it may not be possible to load classes that are not in the java.base module. with: Extreme care should also be taken with JNI FindClass as it may not be possible to load classes, and attempts to do so could result in abrupt termination of the VM.
05-01-2017