test/jdk/java/lang/invoke/VarHandles/accessibility/TestFieldLookupAccessibility.java
changeset 54295 49c4b23d8d0a
parent 47216 71c04702a3d5
equal deleted inserted replaced
54294:add0810ec2fa 54295:49c4b23d8d0a
    20  * or visit www.oracle.com if you need additional information or have any
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    21  * questions.
    22  */
    22  */
    23 
    23 
    24 /* @test
    24 /* @test
    25  * @bug 8152645
    25  * @bug 8152645 8216558
    26  * @summary test field lookup accessibility of MethodHandles and VarHandles
    26  * @summary test field lookup accessibility of MethodHandles and VarHandles
    27  * @compile TestFieldLookupAccessibility.java
    27  * @compile TestFieldLookupAccessibility.java
    28  *          pkg/A.java pkg/B_extends_A.java pkg/C.java
    28  *          pkg/A.java pkg/B_extends_A.java pkg/C.java
    29  *          pkg/subpkg/B_extends_A.java pkg/subpkg/C.java
    29  *          pkg/subpkg/B_extends_A.java pkg/subpkg/C.java
    30  * @run testng/othervm TestFieldLookupAccessibility
    30  * @run testng/othervm TestFieldLookupAccessibility
    94         },
    94         },
    95         MH_UNREFLECT_GETTER_ACCESSIBLE() {
    95         MH_UNREFLECT_GETTER_ACCESSIBLE() {
    96             Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
    96             Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
    97                 return l.unreflectGetter(cloneAndSetAccessible(f));
    97                 return l.unreflectGetter(cloneAndSetAccessible(f));
    98             }
    98             }
       
    99 
       
   100             // Setting the accessibility bit of a Field grants access under
       
   101             // all conditions for MethodHandle getters.
       
   102             Set<String> inaccessibleFields(Set<String> inaccessibleFields) {
       
   103                 return new HashSet<>();
       
   104             }
    99         },
   105         },
   100         MH_UNREFLECT_SETTER() {
   106         MH_UNREFLECT_SETTER() {
   101             Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
   107             Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
   102                 return l.unreflectSetter(f);
   108                 return l.unreflectSetter(f);
   103             }
   109             }
   104 
   110 
   105             boolean isAccessible(Field f) {
   111             boolean isAccessible(Field f) {
   106                 return f.isAccessible() || !Modifier.isFinal(f.getModifiers());
   112                 return f.isAccessible() && !Modifier.isStatic(f.getModifiers()) || !Modifier.isFinal(f.getModifiers());
   107             }
   113             }
   108         },
   114         },
   109         MH_UNREFLECT_SETTER_ACCESSIBLE() {
   115         MH_UNREFLECT_SETTER_ACCESSIBLE() {
   110             Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
   116             Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
   111                 return l.unreflectSetter(cloneAndSetAccessible(f));
   117                 return l.unreflectSetter(cloneAndSetAccessible(f));
       
   118             }
       
   119 
       
   120             boolean isAccessible(Field f) {
       
   121                 return !(Modifier.isStatic(f.getModifiers()) && Modifier.isFinal(f.getModifiers()));
       
   122             }
       
   123 
       
   124             // Setting the accessibility bit of a Field grants access to non-static
       
   125             // final fields for MethodHandle setters.
       
   126             Set<String> inaccessibleFields(Set<String>inaccessibleFields) {
       
   127                 Set<String> result = new HashSet<>();
       
   128                 inaccessibleFields.stream()
       
   129                                   .filter(f -> (f.contains("static") && f.contains("final")))
       
   130                                   .forEach(result::add);
       
   131                 return result;
   112             }
   132             }
   113         },
   133         },
   114         VH() {
   134         VH() {
   115             Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
   135             Object lookup(MethodHandles.Lookup l, Field f) throws Exception {
   116                 return l.findVarHandle(f.getDeclaringClass(), f.getName(), f.getType());
   136                 return l.findVarHandle(f.getDeclaringClass(), f.getName(), f.getType());
   138         // Look up a handle to a field
   158         // Look up a handle to a field
   139         abstract Object lookup(MethodHandles.Lookup l, Field f) throws Exception;
   159         abstract Object lookup(MethodHandles.Lookup l, Field f) throws Exception;
   140 
   160 
   141         boolean isAccessible(Field f) {
   161         boolean isAccessible(Field f) {
   142             return true;
   162             return true;
       
   163         }
       
   164 
       
   165         Set<String> inaccessibleFields(Set<String> inaccessibleFields) {
       
   166             return new HashSet<>(inaccessibleFields);
   143         }
   167         }
   144 
   168 
   145         static Field cloneAndSetAccessible(Field f) throws Exception {
   169         static Field cloneAndSetAccessible(Field f) throws Exception {
   146             // Clone to avoid mutating source field
   170             // Clone to avoid mutating source field
   147             f = f.getDeclaringClass().getDeclaredField(f.getName());
   171             f = f.getDeclaringClass().getDeclaredField(f.getName());
   178     }
   202     }
   179 
   203 
   180     @Test(dataProvider = "lookupProvider")
   204     @Test(dataProvider = "lookupProvider")
   181     public void test(FieldLookup fl, Class<?> src, MethodHandles.Lookup l, Set<String> inaccessibleFields) {
   205     public void test(FieldLookup fl, Class<?> src, MethodHandles.Lookup l, Set<String> inaccessibleFields) {
   182         // Add to the expected failures all inaccessible fields due to accessibility modifiers
   206         // Add to the expected failures all inaccessible fields due to accessibility modifiers
   183         Set<String> expected = new HashSet<>(inaccessibleFields);
   207         Set<String> expected = fl.inaccessibleFields(inaccessibleFields);
   184         Map<Field, Throwable> actual = new HashMap<>();
   208         Map<Field, Throwable> actual = new HashMap<>();
   185 
   209 
   186         for (Field f : fields(src)) {
   210         for (Field f : fields(src)) {
   187             // Add to the expected failures all inaccessible fields due to static/final modifiers
   211             // Add to the expected failures all inaccessible fields due to static/final modifiers
   188             if (!fl.isAccessible(f)) {
   212             if (!fl.isAccessible(f)) {
   200 
   224 
   201         Set<String> actualFieldNames = actual.keySet().stream().map(Field::getName).
   225         Set<String> actualFieldNames = actual.keySet().stream().map(Field::getName).
   202                 collect(Collectors.toSet());
   226                 collect(Collectors.toSet());
   203         if (!actualFieldNames.equals(expected)) {
   227         if (!actualFieldNames.equals(expected)) {
   204             if (actualFieldNames.isEmpty()) {
   228             if (actualFieldNames.isEmpty()) {
   205                 // Setting the accessibility bit of a Field grants access under
   229                 Assert.assertEquals(actualFieldNames, expected, "No accessibility failures:");
   206                 // all conditions for MethodHander getters and setters
       
   207                 if (fl != FieldLookup.MH_UNREFLECT_GETTER_ACCESSIBLE &&
       
   208                     fl != FieldLookup.MH_UNREFLECT_SETTER_ACCESSIBLE) {
       
   209                     Assert.assertEquals(actualFieldNames, expected, "No accessibility failures:");
       
   210                 }
       
   211             }
   230             }
   212             else {
   231             else {
   213                 Assert.assertEquals(actualFieldNames, expected, "Accessibility failures differ:");
   232                 Assert.assertEquals(actualFieldNames, expected, "Accessibility failures differ:");
   214             }
   233             }
   215         }
   234         }