< prev index next >

src/java.base/share/classes/java/lang/invoke/MethodHandles.java

Print this page
@@ -3053,10 +3053,16 @@
           * The method handle will take no arguments.
           * Access checking is performed immediately on behalf of the lookup class.
           * <p>
           * If the returned method handle is invoked, the field's class will
           * be initialized, if it has not already been initialized.
+          * {@link ExceptionInInitializerError} is thrown if invoking the method handle
+          * provokes the class to be initialized and the initializer fails.
+          * {@link IllegalStateException} is thrown if the field is a {@linkplain
+          * Field#isStrictInit() strictly-initialized} static field and the method handle
+          * is invoked by the thread initializing the field's class before the field has
+          * been initialized.
           * @param refc the class or interface from which the method is accessed
           * @param name the field's name
           * @param type the field's type
           * @return a method handle which can load values from the field
           * @throws NoSuchFieldException if the field does not exist

@@ -3098,13 +3104,10 @@
           * coordinate types.
           * <p>
           * Access checking is performed immediately on behalf of the lookup
           * class.
           * <p>
-          * If the returned VarHandle is operated on, the declaring class will be
-          * initialized, if it has not already been initialized.
-          * <p>
           * Certain access modes of the returned VarHandle are unsupported under
           * the following conditions:
           * <ul>
           * <li>if the field is declared {@code final}, then the write, atomic
           *     update, numeric atomic update, and bitwise atomic update access

@@ -3126,10 +3129,19 @@
           * <p>
           * If the field type is {@code float} or {@code double} then numeric
           * and atomic update access modes compare values using their bitwise
           * representation (see {@link Float#floatToRawIntBits} and
           * {@link Double#doubleToRawLongBits}, respectively).
+          * <p>
+          * If the returned VarHandle is operated on, the declaring class will be
+          * initialized, if it has not already been initialized.
+          * {@link ExceptionInInitializerError} is thrown if operating on the VarHandle
+          * provokes the class to be initialized and the initializer fails.
+          * {@link IllegalStateException} is thrown if the field is a {@linkplain
+          * Field#isStrictInit() strictly-initialized} static field and the VarHandle
+          * is operated on by the thread initializing the field's class to read the
+          * field before it has been initialized.
           * @apiNote
           * Bitwise comparison of {@code float} values or {@code double} values,
           * as performed by the numeric and atomic update access modes, differ
           * from the primitive {@code ==} operator and the {@link Float#equals}
           * and {@link Double#equals} methods, specifically with respect to

@@ -3388,13 +3400,18 @@
           * Otherwise, its single argument will be the instance containing
           * the field.
           * If the {@code Field} object's {@code accessible} flag is not set,
           * access checking is performed immediately on behalf of the lookup class.
           * <p>
-          * If the field is static, and
-          * if the returned method handle is invoked, the field's class will
-          * be initialized, if it has not already been initialized.
+          * If the field is static, and if the returned method handle is invoked, the
+          * field's class will be initialized, if it has not already been initialized.
+          * {@link ExceptionInInitializerError} is thrown if invoking the method handle
+          * provokes the class to be initialized and the initializer fails.
+          * {@link IllegalStateException} is thrown if the field is a {@linkplain
+          * Field#isStrictInit() strictly-initialized} static field and the method handle
+          * is invoked by the thread initializing the field's class before the field has
+          * been initialized.
           * @param f the reflected field
           * @return a method handle which can load values from the reflected field
           * @throws IllegalAccessException if access checking fails
           * @throws NullPointerException if the argument is null
           */

@@ -3443,10 +3460,15 @@
                  if (field.isTrustedFinalField()) {
                      String msg = field.isStatic() ? "static final field has no write access"
                                                    : "final field has no write access";
                      throw field.makeAccessException(msg, this);
                  }
+                 // strictly-initialized finals not trusted finals at this time
+                 if (field.isStrictInit()) {
+                     throw field.makeAccessException("strictly-initialized final field has no write access", this);
+                 }
+ 
                  // check if write access to final field allowed
                  if (!field.isStatic() && isAccessible) {
                      SharedSecrets.getJavaLangReflectAccess().checkAllowedToUnreflectFinalSetter(lookupClass, f);
                  }
              }

@@ -3467,14 +3489,10 @@
           * <p>
           * Access checking is performed immediately on behalf of the lookup
           * class, regardless of the value of the field's {@code accessible}
           * flag.
           * <p>
-          * If the field is static, and if the returned VarHandle is operated
-          * on, the field's declaring class will be initialized, if it has not
-          * already been initialized.
-          * <p>
           * Certain access modes of the returned VarHandle are unsupported under
           * the following conditions:
           * <ul>
           * <li>if the field is declared {@code final}, then the write, atomic
           *     update, numeric atomic update, and bitwise atomic update access

@@ -3496,10 +3514,20 @@
           * <p>
           * If the field type is {@code float} or {@code double} then numeric
           * and atomic update access modes compare values using their bitwise
           * representation (see {@link Float#floatToRawIntBits} and
           * {@link Double#doubleToRawLongBits}, respectively).
+          * <p>
+          * If the field is static, and if the returned VarHandle is operated
+          * on, the field's declaring class will be initialized, if it has not
+          * already been initialized.
+          * {@link ExceptionInInitializerError} is thrown if operating on the VarHandle
+          * provokes the class to be initialized and the initializer fails.
+          * {@link IllegalStateException} is thrown if the field is a {@linkplain
+          * Field#isStrictInit() strictly-initialized} static field and the VarHandle
+          * is operated on by the thread initializing the field's class to read the
+          * field before it has been initialized.
           * @apiNote
           * Bitwise comparison of {@code float} values or {@code double} values,
           * as performed by the numeric and atomic update access modes, differ
           * from the primitive {@code ==} operator and the {@link Float#equals}
           * and {@link Double#equals} methods, specifically with respect to

@@ -3959,11 +3987,11 @@
                      throw getField.makeAccessException("caller class must be a subclass below the method", lookupClass());
                  }
                  refc = lookupClass();
              }
              return VarHandles.makeFieldHandle(getField, refc,
-                                               this.allowedModes == TRUSTED && !getField.isTrustedFinalField());
+                                               this.allowedModes == TRUSTED);
          }
          /** Check access and get the requested constructor. */
          private MethodHandle getDirectConstructor(Class<?> refc, MemberName ctor) throws IllegalAccessException {
              return getDirectConstructorCommon(refc, ctor);
          }
< prev index next >