5.4.3.6 Dynamically-Computed Constant and Call Site Resolution

To resolve an unresolved symbolic reference R to a dynamically-computed constant or call site, there are three tasks. First, R is examined to determine which code will serve as its bootstrap method, and which arguments will be passed to that code. Second, the arguments are packaged into an array and the bootstrap method is invoked. Third, the result of the bootstrap method is validated, and used as the result of resolution. The first task involves the following steps: 1. R gives a symbolic reference to a bootstrap method handle. The bootstrap method handle is resolved (§5.4.3.5) to obtain a reference to an instance of java.lang.invoke.MethodHandle.

+ Any exception that can be thrown as a result of failure of resolution of a symbolic reference to a method handle can be thrown in this step.

+ If R is a symbolic reference to a dynamically-computed constant, then let D be the type descriptor of the bootstrap method handle. (That is, D is a reference to an instance of java.lang.invoke.MethodType.) The first parameter type indicated by D must be java.lang.invoke.MethodHandles.Lookup, or else resolution fails with a BootstrapMethodError. For historical reasons, the bootstrap method handle for a dynamically-computed call site is not similarly constrained.

+ 2. If R is a symbolic reference to a dynamically-computed constant, then it gives a field descriptor.

+ If the field descriptor indicates a primitive type, then a reference to the pre-defined Class object representing that type is obtained (see the method isPrimitive in class Class).

+ Otherwise, the field descriptor indicates a class or interface type, or an array type. A reference to the Class object representing the type indicated by the field descriptor is obtained, as if by resolution of an unresolved symbolic reference to a class or interface (§5.4.3.1) whose name corresponds to the type indicated by the field descriptor.

+ Any exception that can be thrown as a result of failure of resolution of a symbolic reference to a class or interface can be thrown in this step. 3. If R is a symbolic reference to a dynamically-computed call site, then it gives a method descriptor.

+ A reference to an instance of java.lang.invoke.MethodType is obtained, as if by resolution of an unresolved symbolic reference to a method type (§5.4.3.5) with the same parameter and return types as the method descriptor.

+ Any exception that can be thrown as a result of failure of resolution of a symbolic reference to a method type can be thrown in this step. 4. R gives zero or more static arguments, which communicate application-specific metadata to the bootstrap method. Each static argument A is resolved, in the order given by R, as follows:

  • If A is a string constant, then a reference to its instance of class String is obtained.

  • If A is a numeric constant, then a reference to an instance of java.lang.invoke.MethodHandle is obtained by the following procedure:

    1. Let v be the value of the numeric constant, and let T be a field descriptor which corresponds to the type of the numeric constant.

    2. Let MH be a method handle produced as if by invocation of the identity method of java.lang.invoke.MethodHandles with an argument representing the class Object.

    3. A reference to an instance of java.lang.invoke.MethodHandle is obtained as if by the invocation MH.invoke(v) with method descriptor (T)Ljava/lang/Object;.

  • If A is a symbolic reference to a dynamically-computed constant with a field descriptor indicating a primitive type T, then A is resolved, producing a primitive value v. Given v and T, a reference is obtained to an instance of java.lang.invoke.MethodHandle according to the procedure specified above for numeric constants.

  • If A is any other kind of symbolic reference, then the result is the result of resolving A. Among the symbolic references in the run-time constant pool, symbolic references to dynamically-computed constants are special because they are derived from constant_pool entries that can syntactically refer to themselves via the BootstrapMethods attribute (§4.7.23). However, the Java Virtual Machine does not support resolving a symbolic reference to a dynamically-computed constant that depends on itself (that is, as a static argument to its own bootstrap method). Accordingly, when both R and A are symbolic references to dynamically-computed constants, if A is the same as R or A gives a static argument that (directly or indirectly) references R, then resolution fails with a StackOverflowError at the point where re-resolution of R would be required. Unlike class initialization (§5.5), where cycles are allowed between uninitialized classes, resolution does not allow cycles in symbolic references to dynamically-computed constants. If an implementation of resolution makes recursive use of a stack, then a StackOverflowError will occur naturally. If not, the implementation is required to detect the cycle rather than, say, looping infinitely or returning a default value for the dynamically-computed constant. A similar cycle may arise if the body of a bootstrap method makes reference to a dynamically-computed constant currently being resolved. This has always been possible for invokedynamic bootstraps, and does not require special treatment in resolution; the recursive invokeWithArguments calls will naturally lead to a StackOverflowError. Any exception that can be thrown as a result of failure of resolution of a symbolic reference can be thrown in this step. The second task, to invoke the bootstrap method handle, involves the following steps:

    1. An array is allocated with component type Object and length n+3, where n is the number of static arguments given by R (n ≥ 0).

      The zeroth component of the array is set to a reference to an instance of java.lang.invoke.MethodHandles.Lookup for the class in which R occurs, produced as if by invocation of the lookup method of java.lang.invoke.MethodHandles.

      The first component of the array is set to a reference to an instance of String that denotes N, the unqualified name given by R.

      The second component of the array is set to the reference to an instance of Class or java.lang.invoke.MethodType that was obtained earlier for the field descriptor or method descriptor given by R.

      Subsequent components of the array are set to the references that were obtained earlier from resolving R’s static arguments, if any. The references appear in the array in the same order as the corresponding static arguments are given by R.

      A Java Virtual Machine implementation may be able to skip allocation of the array and, without any change in observable behavior, pass the arguments directly to the bootstrap method.

    2. The bootstrap method handle is invoked, as if by the invocation BMH.invokeWithArguments(args), where BMH is the bootstrap method handle and args is the array allocated above.

      Due to the behavior of the invokeWithArguments method of java.lang.invoke.MethodHandle, the type descriptor of the bootstrap method handle need not exactly match the run-time types of the arguments. For example, the second parameter type of the bootstrap method handle (corresponding to the unqualified name given in the first component of the array above) could be Object instead of String. If the bootstrap method handle is variable arity, then some or all of the arguments may be collected into a trailing array parameter.

      The invocation occurs within a thread that is attempting resolution of this symbolic reference. If there are several such threads, the bootstrap method handle may be invoked concurrently. Bootstrap methods which access global application data should take the usual precautions against race conditions.

      If the invocation fails by throwing an instance of Error or a subclass of Error, resolution fails with that exception.

      If the invocation fails by throwing an exception that is not an instance of Error or a subclass of Error, resolution fails with a BootstrapMethodError whose cause is the thrown exception.

      If several threads concurrently invoke the bootstrap method handle for this symbolic reference, the Java Virtual Machine chooses the result of one invocation and installs it visibly to all threads. Any other bootstrap methods executing for this symbolic reference are allowed to complete, but their results are ignored. The third task, to validate the reference, o, produced by invocation of the bootstrap method handle, is as follows:

  • If R is a symbolic reference to a dynamically-computed constant, then o is converted to type T, the type indicated by the field descriptor given by R.

    o’s conversion occurs as if by the invocation MH.invoke(o) with method descriptor (Ljava/lang/Object;)T, where MH is a method handle produced as if by invocation of the identity method of java.lang.invoke.MethodHandles with an argument representing the class Object.

    The result of o’s conversion is the result of resolution.

    If the conversion fails by throwing a NullPointerException or a ClassCastException, resolution fails with a BootstrapMethodError.

  • If R is a symbolic reference to a dynamically-computed call site, then o is the result of resolution if it has all of the following properties:

    • o is not null.

    • o is an instance of java.lang.invoke.CallSite or a subclass of java.lang.invoke.CallSite.

    • The type of the java.lang.invoke.CallSite is semantically equal to the method descriptor given by R. If o does not have these properties, resolution fails with a BootstrapMethodError. Many of the steps above perform computations "as if by invocation" of certain methods. In each case, the invocation behavior is given in detail by the specifications for invokestatic and invokevirtual. The invocation occurs in the thread and from the class that is attempting resolution of the symbolic reference R. However, no corresponding method references are required to appear in the run-time constant pool, no particular method’s operand stack is necessarily used, and the value of the max_stack item of any method’s Code attribute is not enforced for the invocation. If several threads attempt resolution of R at the same time, the bootstrap method may be invoked concurrently. Therefore, bootstrap methods which access global application data must take precautions against race conditions.

贡献翻译,请加 QQ: 840750575    点击这里给我发消息
数码
沪ICP备19006215号-4