JDK-8160527 : Check for final instance field updates can be omitted
  • Type: Bug
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 9
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2016-06-29
  • Updated: 2016-08-18
  • Resolved: 2016-07-06
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 9
9 b129Fixed
Related Reports
Blocks :  
Relates :  
Relates :  
Description
JDK-8157181 implemented a new check for final field update. The new check verifies if (static) final field are updated only in (class) initializers.

In a comment added to JDK-8157181, John Rose has pointed out a flaw in the checking logic implemented by JDK-8157181. The flaw affects only instance field updates.

Here are John's comments on the issue:

"...there appears to be a hole in the JVM's logic which blocks non-<init> methods from running putfield on final fields. Probably you know about this, but I'll write it here just in case.

Suppose the interpreter executes a putfield on a final field in an <init> method, which causes a call to LinkResolver::resolve_field_access that succeeds. At that point, InterpreterRuntime::resolve_get_put updates the CP cache entry for the field reference.

Later on, with the CP cache initialized for "puts" to that field, a random method (not an <init> method) in the same class executes a putfield on that final field. The assembly code checks the CP cache and takes the fast path. The new logic in the changes for JDK-8157181 never gets executed, because it is on the slow path.

The root issue is that the cached resolution information in the CP cache is shared between <init> and non-<init> methods.

BTW, I like the fact that, whatever happens with resolution, the rewriter has already scanned for malformed puts to finals, and has set a bit telling the JIT to distrust those fields. This means we shouldn't have mis-optimization even if I'm right about the above weakness in resolution checking.

Perhaps there is some way to have resolve_get_put refuse to "quicken" the CP cache for a put of a final field, *if* the "has_initialized_final_update" bit has been set by the rewriter. In that case, the slow path would get run all the time for resolution. However, I don't see a way to do this without significant changes to the assembly code."