Relates :
|
|
Relates :
|
|
Relates :
|
There are a number of areas in the JVMS where linking (methods, constants, or indy call sites) can result in a BootstrapMethodError that wraps any Throwable. This can cause problems and confusion e.g. when an asynchronous exception such as ThreadDeath occurs when linking. Such areas include: 1) invokedynamic, which is specified in JVMS8 to wrap all exceptions in a BootstrapMethodError (where JVMS8 elsewhere states that "exception" really means java.lang.Throwable or a subtype). As an example this can easily be induced with string concatenation that uses indy concat. 2) the linking of signature-polymorphic methods on MethodHandle and VarHandle. 3) the loading of MethodType and MethodHandle constants in the constant pool. Unfortunately, JVMS8 is logically wrong, because some Throwables must *not* be wrapped in BootstrapMethodError. These include LinkageErrors from "continuing resolution steps", when those steps (for example) are semantically visible to the Java language, e.g., when invokedynamic implements Java member references (Foo::bar, where a failure to resolve bar *must* throw a LinkageError for bar). The specification for cases 2 and 3 could be fixed merely by adding new cases to JVMS 6.5, or by loosening the wording of JVMS 6.5 to allow things like ThreadDeath to "creep in", or by loosening wording elsewhere about linkage exceptions. However, the specification for invokedynamic (case 1) is in direct conflict with present and future uses of the instruction to implement "virtualized linkage semantics" of present and future language features. The spec needs to be relaxed to wrap only those exceptions (Throwables) which *cannot* be relevant to the link-time semantics of a language feature being implemented by invokedynamic. The simplest way to carry this out would be to amend JVMS 6.5 (and the HotSpot RI) to pass Error (and *all* its subtypes) without wrapping, if the linkage of invokedynamic throws such a thing. Such an amendment has many desirable properties: - It ensures that if a LinkageError, ThreadDeath, or any of the JVMS 6.3 "special" VM errors are thrown, the BSME wrapping process will not touch or interfere with them. There are many baroque subtypes of Error but in practice the ones thrown as part of linkage are special enough to the JVM that wrapping them in BSME defeats their purpose. The most "special" Error subtypes are listed in JVMS 6.3, though this list itself cannot be regarded as complete since ThreadDeath should never be wrapped (notwithstanding the legacy behavior of j.l.r.Method.invoke). - Allowing any Error to propagate outside of a BSM allows the linkage behavior for specific invokedynamic bootstrap methods to include useful new subtypes of Error as outcomes for linking new language features, without interfering with the JVMS. This is appropriate for invokedynamic since it (unlike the other invocation modes) is a virtualized instruction, with little hardwired behavior. When invokedynamic is used to emulate hardwired JVM behavior (e.g., invokevirtual), its bootstrap method can filter exceptions by wrapping Errors mandated-by-the-JVMS-to-be-wrapped-for-that-hardwired-JVM-behavior either in LinkageError, BootstrapMethodError, UnknownError, or some other wrapping chosen by the author of the bootstrap method, based on the requirements for the particular use case. - Not wrapping Error allows the correct wrapping of java.lang.Exception (even though we don't mention that type in the JVMS), thus preserving the integrity of Java's venerable exception checking framework. That is, the linking of invokedynamic must not throw a "checked exception", nor a subtype of RuntimeException, at link time.
|