1 /* 2 * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /** 25 * @test 26 * @build Fields HiddenClassTest 27 * @run testng/othervm HiddenClassTest 28 * @summary Test java.lang.reflect.AccessibleObject with modules 29 */ 30 31 import java.io.IOException; 32 import java.io.UncheckedIOException; 33 import java.lang.invoke.MethodHandles; 34 import java.lang.reflect.Field; 35 import java.lang.reflect.Modifier; 36 import java.nio.file.Files; 37 import java.nio.file.Path; 38 import java.nio.file.Paths; 39 40 import org.testng.annotations.Test; 41 import static org.testng.Assert.*; 42 43 public class HiddenClassTest { 44 static final Class<?> hiddenClass = defineHiddenClass(); 45 private static Class<?> defineHiddenClass() { 46 String classes = System.getProperty("test.classes"); 47 Path cf = Paths.get(classes, "Fields.class"); 48 try { 49 byte[] bytes = Files.readAllBytes(cf); 50 return MethodHandles.lookup().defineHiddenClass(bytes, true).lookupClass(); 51 } catch (IOException e) { 52 throw new UncheckedIOException(e); 53 } catch (IllegalAccessException e) { 54 throw new RuntimeException(e); 55 } 56 } 57 58 /* 59 * Test Field::set that can write the value of a non-static final field 60 * in a normal class 61 */ 62 @Test 63 public void testFieldsInNormalClass() throws Throwable { 64 // despite the name "HiddenClass", this class is loaded by the 65 // class loader as non-hidden class 66 Class<?> c = Fields.class; 67 Fields o = new Fields(); 68 assertFalse(c.isHidden()); 69 readOnlyAccessibleObject(c, "STATIC_FINAL", null, true); 70 readWriteAccessibleObject(c, "STATIC_NON_FINAL", null, false); 71 readWriteAccessibleObject(c, "FINAL", o, true); 72 readWriteAccessibleObject(c, "NON_FINAL", o, false); 73 } 74 75 /* 76 * Test Field::set that fails to write the value of a non-static final field 77 * in a hidden class 78 */ 79 @Test 80 public void testFieldsInHiddenClass() throws Throwable { 81 assertTrue(hiddenClass.isHidden()); 82 Object o = hiddenClass.newInstance(); 83 readOnlyAccessibleObject(hiddenClass, "STATIC_FINAL", null, true); 84 readWriteAccessibleObject(hiddenClass, "STATIC_NON_FINAL", null, false); 85 readOnlyAccessibleObject(hiddenClass, "FINAL", o, true); 86 readWriteAccessibleObject(hiddenClass, "NON_FINAL", o, false); 87 } 88 89 private static void readOnlyAccessibleObject(Class<?> c, String name, Object o, boolean isFinal) throws Exception { 90 Field f = c.getDeclaredField(name); 91 int modifier = f.getModifiers(); 92 if (isFinal) { 93 assertTrue(Modifier.isFinal(modifier)); 94 } else { 95 assertFalse(Modifier.isFinal(modifier)); 96 } 97 assertTrue(f.trySetAccessible()); 98 assertTrue(f.get(o) != null); 99 try { 100 f.set(o, null); 101 assertTrue(false, "should fail to set " + name); 102 } catch (IllegalAccessException e) { 103 } 104 } 105 106 private static void readWriteAccessibleObject(Class<?> c, String name, Object o, boolean isFinal) throws Exception { 107 Field f = c.getDeclaredField(name); 108 int modifier = f.getModifiers(); 109 if (isFinal) { 110 assertTrue(Modifier.isFinal(modifier)); 111 } else { 112 assertFalse(Modifier.isFinal(modifier)); 113 } 114 assertTrue(f.trySetAccessible()); 115 assertTrue(f.get(o) != null); 116 try { 117 f.set(o, null); 118 } catch (IllegalAccessException e) { 119 throw e; 120 } 121 } 122 }