1 /* 2 * Copyright (c) 2017, 2018, 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 /* 26 * @test 27 * @summary test reflection on inline types 28 * @compile -XDallowWithFieldOperator Point.java Line.java NonFlattenValue.java 29 * @run main/othervm -XX:+EnableValhalla Reflection 30 */ 31 32 import java.lang.reflect.*; 33 import java.util.Arrays; 34 import java.util.stream.Collectors; 35 36 public class Reflection { 37 public static void main(String... args) throws Exception { 38 testPointClass(); 39 testLineClass(); 40 testNonFlattenValue(); 41 testMirrors(); 42 testClassName(); 43 } 44 45 static void testPointClass() throws Exception { 46 Point o = Point.makePoint(10, 20); 47 Reflection test = new Reflection(Point.class, "Point", o); 48 test.newInstance(); 49 test.constructor(); 50 test.accessFieldX(o.x); 51 test.setAccessible(); 52 test.trySetAccessible(); 53 test.staticField(); 54 } 55 56 static void testLineClass() throws Exception { 57 Line l = Line.makeLine(10, 20, 30, 40); 58 Reflection test = new Reflection(Line.class, "Line", l); 59 test.checkField("public final Point Line.p1", "p1", Point.class); 60 test.checkField("public final Point Line.p2", "p2", Point.class); 61 test.checkMethod("public Point Line.p1()", "p1", Point.class); 62 test.checkMethod("public Point Line.p2()", "p2", Point.class); 63 } 64 65 static void testNonFlattenValue() throws Exception { 66 NonFlattenValue nfv = NonFlattenValue.make(10, 20); 67 Reflection test = new Reflection(NonFlattenValue.class, "NonFlattenValue", nfv); 68 test.checkField("final Point? NonFlattenValue.nfp", "nfp", Point.class.asNullableType()); 69 test.checkMethod("public Point NonFlattenValue.pointValue()", "pointValue", Point.class); 70 test.checkMethod("public Point? NonFlattenValue.point()", "point", Point.class.asNullableType()); 71 test.checkMethod("public boolean NonFlattenValue.has(Point,Point?)", "has", boolean.class, Point.class, Point.class.asNullableType()); 72 } 73 74 /* 75 * Tests reflection APIs with the primary and nullable mirror 76 */ 77 static void testMirrors() throws Exception { 78 Class<?> primary = Point.class; 79 Class<?> nullable = Point.class.asNullableType(); 80 81 assertEquals(primary, Point.class); 82 assertTrue(primary.isInlineClass()); 83 assertTrue(nullable.isInlineClass()); 84 85 Point o = Point.makePoint(10, 20); 86 assertTrue(primary.isInstance(o)); 87 assertTrue(nullable.isInstance(o)); 88 89 // V <: V? and V <: Object 90 assertTrue(nullable.isAssignableFrom(primary)); 91 assertTrue(Object.class.isAssignableFrom(primary)); 92 assertFalse(primary.isAssignableFrom(nullable)); 93 assertTrue(Object.class.isAssignableFrom(nullable)); 94 95 assertEquals(primary, primary.asSubclass(nullable)); 96 try { 97 Class<?> c = nullable.asSubclass(primary); 98 assertTrue(false); 99 } catch (ClassCastException e) { } 100 } 101 102 static void testClassName() { 103 assertEquals(Point.class.getName(), "Point"); 104 assertEquals(Point.class.asNullableType().getName(), "Point"); 105 assertEquals(Line.class.getName(), "Line"); 106 assertEquals((new Point[0]).getClass().getName(), "[QPoint;"); 107 assertEquals((new Point?[0][0]).getClass().getName(), "[[LPoint;"); 108 } 109 110 private final Class<?> c; 111 private final Constructor<?> ctor; 112 private final Object o; 113 Reflection(Class<?> type, String cn, Object o) throws Exception { 114 this.c = Class.forName(cn); 115 if (!c.isInlineClass() || c != type) { 116 throw new RuntimeException(cn + " is not an inline class"); 117 } 118 119 // V.class, Class.forName, and the type of the object return the primary mirror 120 assertEquals(type, o.getClass()); 121 assertEquals(type, c.asPrimaryType()); 122 assertEquals(c, c.asPrimaryType()); 123 124 this.ctor = c.getDeclaredConstructor(); 125 this.o = o; 126 127 128 // test the primary mirror and secondary mirror 129 testMirrors(this.c); 130 // test array of Q-type and L-type 131 testArray(c.asPrimaryType()); 132 testArray(c.asNullableType()); 133 } 134 135 private static void testMirrors(Class<?> c) { 136 Class<?> inlineType = c.asPrimaryType(); 137 Class<?> nullableType = c.asNullableType(); 138 139 assertTrue(inlineType != null); 140 assertEquals(nullableType.getTypeName(), c.getTypeName() + "?"); 141 142 assertEquals(nullableType.getName(), inlineType.getName()); 143 assertEquals(nullableType.getTypeName(), inlineType.getTypeName() + "?"); 144 assertEquals(inlineType.asNullableType(), nullableType); 145 assertEquals(nullableType.asPrimaryType(), inlineType); 146 } 147 148 void testArray(Class<?> elementType) { 149 Object[] array = (Object[])Array.newInstance(elementType, 1); 150 Class<?> arrayType = array.getClass(); 151 assertTrue(arrayType.isArray()); 152 Class<?> componentType = arrayType.getComponentType(); 153 assertTrue(componentType.isInlineClass()); 154 assertEquals(componentType, elementType); 155 // Array is a reference type 156 assertEquals(arrayType.asNullableType(), arrayType); 157 if (array[0] == null) { 158 System.out.println("array[0] = null"); 159 } else { 160 System.out.println("array[0] = " + array[0]); 161 } 162 } 163 164 void accessFieldX(int x) throws Exception { 165 Field field = c.getField("x"); 166 if (field.getInt(o) != x) { 167 throw new RuntimeException("Unexpected Point.x value: " + field.getInt(o)); 168 } 169 170 try { 171 field.setInt(o, 100); 172 throw new RuntimeException("IllegalAccessException not thrown"); 173 } catch (IllegalAccessException e) {} 174 } 175 176 void newInstance() throws Exception { 177 try { 178 Object o = c.newInstance(); 179 throw new RuntimeException("newInstance expected to be unsupported on inline class"); 180 } catch (IllegalAccessException e) {} 181 } 182 183 void constructor() throws Exception { 184 try { 185 ctor.newInstance(); 186 throw new RuntimeException("IllegalAccessException not thrown"); 187 } catch (IllegalAccessException e) { } 188 } 189 190 void setAccessible() throws Exception { 191 try { 192 ctor.setAccessible(true); 193 throw new RuntimeException("InaccessibleObjectException not thrown"); 194 } catch (InaccessibleObjectException e) { e.printStackTrace(); } 195 Field field = c.getField("x"); 196 try { 197 field.setAccessible(true); 198 throw new RuntimeException("InaccessibleObjectException not thrown"); 199 } catch (InaccessibleObjectException e) { e.printStackTrace(); } 200 } 201 202 void trySetAccessible() throws Exception { 203 if (ctor.trySetAccessible()) { 204 throw new RuntimeException("trySetAccessible should not succeed"); 205 } 206 Field field = c.getField("x"); 207 if (field.trySetAccessible()) { 208 throw new RuntimeException("trySetAccessible should not succeed"); 209 } 210 } 211 212 void staticField() throws Exception { 213 Field f = c.getDeclaredField("STATIC_FIELD"); 214 if (f.trySetAccessible()) { 215 throw new RuntimeException("trySetAccessible should not succeed"); 216 } 217 try { 218 f.setAccessible(true); 219 throw new RuntimeException("IllegalAccessException not thrown"); 220 } catch (InaccessibleObjectException e) { } 221 } 222 223 void checkField(String source, String name, Class<?> type) throws Exception { 224 Field f = c.getDeclaredField(name); 225 assertEquals(f.getType(), type); 226 assertEquals(f.toString(), source); 227 } 228 229 void checkMethod(String source, String name, Class<?> returnType, Class<?>... params) throws Exception { 230 Method m = c.getDeclaredMethod(name, params); 231 assertEquals(m.toString(), source); 232 } 233 234 static void assertEquals(Object o1, Object o2) { 235 if (o1 == o2 || o1.equals(o2)) 236 return; 237 238 throw new AssertionError(o1 + " != " + o2); 239 } 240 241 static void assertTrue(boolean value) { 242 if (!value) 243 throw new AssertionError("expected true"); 244 } 245 246 static void assertFalse(boolean value) { 247 if (value) 248 throw new AssertionError("expected false"); 249 } 250 }