(Nestmates) RFR (M): 8240645: Update nest host determination in line with latest proposed JVMS changes for JEP-371
David Holmes
david.holmes at oracle.com
Fri Mar 6 05:29:53 UTC 2020
webrev: http://cr.openjdk.java.net/~dholmes/8240645/webrev/
bug: https://bugs.openjdk.java.net/browse/JDK-8240645
JEP-371 (Hidden Classes) is changing a key aspect of nest host
resolution and validation compared to what we shipped originally for
JEP-181 (Nestmates). Originally, any LinkageErrors during nest host
resolution would be propagated, and any validation failures would result
in IncompatibleClassChangeError being thrown. Now no LinkageErrors are
thrown, but the fact one occurred is remembered for potential use if a
private access check fails. Similarly, validation failures don't cause
an exception any more. Nest host resolution always succeeds and the nest
will be one of:
- the successfully resolved nest host as per the NestHost attribute
- the class itself if there is no NestHost attribute or there is an
error during resolution or validation
- the specified nest host explicitly set if this is a hidden class
injected into a nest
as appropriate.
This has a flow on affect to the reflection method
Class::getNestMembers() which can also no longer ever fail.
To be able to diagnose issues with nest host resolution/validation you
can use unified logging to examine what happens:
-Xlog:class+nestmates=trace.
In addition IllegakAccessErrors thrown by the VM are augmented with
information about any nest host resolution/validation errors. For
example an original exception:
java.lang.IllegalAccessError: class TestNestmateMembership$Caller tried
to access private method 'void
TestNestmateMembership$TargetSelfHost.m()'
(TestNestmateMembership$Caller and TestNestmateMembership$TargetSelfHost
are in unnamed module of loader 'app')
is now expanded with an additional "(<nest host resolution error(s)>)"
section which is memoized for use with other access checks:
java.lang.IllegalAccessError: class TestNestmateMembership$Caller tried
to access private method 'void
TestNestmateMembership$TargetSelfHost.m()'
(TestNestmateMembership$Caller and TestNestmateMembership$TargetSelfHost
are in unnamed module of loader 'app')(Type
TestNestmateMembership$TargetSelfHost (loader: 'app') is not a nest
member of type TestNestmateMembership$TargetSelfHost (loader: 'app'):
current type is not listed as a nest member)
These exception messages are very long and unweildy but that seems
unavoidable. They appear repetative in that the type names appear in the
main message, the module information, and then again in the resolution
error section. Unfortunately we can't avoid that as the memoized string
has to be complete because it does not know the context of the
IllegalAccessError in which it will be used. Please look at the
mechanism by which this is done before making suggestions on how to
condense.
Also note that in the worst case there can be two nest host resolution
errors reported, if both the current class and the target class had such
errors.
Note: the augmented exceptions do not extend to IllegalAccessExceptions
thrown by the Java reflection or MethodHandle code. This would require
an additional VM call to retrieve the information. This may be
considered for a future RFE.
Changes in detail:
- src/hotspot/share/ci/ciField.cpp
- src/hotspot/share/classfile/classFileParser.cpp
- src/hotspot/share/runtime/reflection.cpp
No longer a possibility of exceptions
- src/hotspot/share/interpreter/linkResolver.cpp
Expands on the message for IllegalAccessErrors in the private case, to
report any nest host resolution/validation errors.
- src/hotspot/share/oops/instanceKlass.cpp
Implements the new specification for resolving the nest host, and adds
the means to memoize the error message. The same message is used for
exceptions and logging.
Exception handling is changed as needed - no use of CHECK macros.
Removed a case in has_nest_member where we would bail out if executing
in a compiler thread and encountered an unresolved class entry in the
CP. We previously bailed out as a precaution as the compiler thread
can't load classes. I was surprised to find that I was hitting this
code, and getting runtime failures because of it (not test failures). I
don't see how the current changes would cause this. In any case the
situation where actual class loading would be needed should be
impossible - two classes of the same name within the same loader - so
the bail out can be removed.
Removed the recently added runtime_nest_host code which is no longer needed.
- src/hotspot/share/prims/jvm.cpp
Some code simplifies now exceptions are no longer possible.
JVM_GetNestMembers has major updates:
- as we no longer bail out on error we may end up with holes in the
array, so we have to copy across to an array of the exact size before
returning.
- added logging to aid in debugging
- src/hotspot/share/utilities/ostream.cpp
Needed to add the ability for stringStream to return a C-Heap allocated
buffer so we could use it for the memoized error messages. (This should
probably be factored out to a separate RFE for mainline.)
- src/java.base/share/classes/java/lang/Class.java
Updated the specifications for getNestHost and getNestMembers as per
Mandy's proposed spec updates (added missing @jvms links in
getNestMembers()). Adjusted the implementation for the fact there are no
longer any exceptions from the VM.
-
test/hotspot/jtreg/runtime/Nestmates/membership/TestNestmateMembership.java
Had to change all the LinkageErrors/NoClassDefFoundErrors to be
IllegalAccessError or IllegalAccessException and adjust the expected
messages to check the underlying failure reasons.
Other test adjusted as needed to account for no exceptions, and the
changes to Class::getNestMembers().
Testing: all nestmate and hidden class tests under normal conditions.
tiers 1 - 3
Thanks,
David
More information about the valhalla-dev
mailing list