1 /* 2 * Copyright (c) 2019, 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 of constructors for inline classes 28 * @run main/othervm -XX:+EnableValhalla InlineConstructorTest 29 */ 30 31 import java.lang.reflect.Constructor; 32 import java.lang.reflect.Field; 33 import java.lang.reflect.InaccessibleObjectException; 34 import java.lang.reflect.Method; 35 import java.lang.reflect.Modifier; 36 import java.util.Arrays; 37 import java.util.Set; 38 import java.util.stream.Collectors; 39 40 public class InlineConstructorTest { 41 42 // Target test class 43 static inline class SimpleInline { 44 public final int x; 45 46 SimpleInline() { 47 x = -1; 48 } 49 50 public SimpleInline(int x) { 51 this.x = x; 52 } 53 } 54 55 private final Class<?> c; 56 57 public static void main(String... args) throws Exception { 58 testSimpleInlineClass(); 59 } 60 61 static void testSimpleInlineClass() throws Exception { 62 InlineConstructorTest test = new InlineConstructorTest(SimpleInline.class); 63 test.constructor(); 64 test.constructors("public InlineConstructorTest$SimpleInline(int)", 65 "InlineConstructorTest$SimpleInline()"); 66 test.setAccessible(); 67 test.trySetAccessible(); 68 test.initFactoryNotMethods(); 69 } 70 71 InlineConstructorTest(Class<?> type) throws Exception { 72 String cn = type.getName(); 73 this.c = Class.forName(cn); 74 75 assertTrue(c.isInlineClass()); 76 assertEquals(c, type); 77 } 78 79 void constructor() throws Exception { 80 Constructor<?> ctor = c.getDeclaredConstructor(); 81 Object o = ctor.newInstance(); 82 assertEquals(o.getClass(), c); 83 } 84 85 // Check that the class has the expected Constructors 86 void constructors(String... expected) throws Exception { 87 Constructor<? extends Object>[] cons = c.getDeclaredConstructors(); 88 Set<String> actualSig = 89 Arrays.stream(cons).map(Constructor::toString).collect(Collectors.toSet()); 90 Set<String> expectedSig = Set.of(expected); 91 boolean ok = expectedSig.equals(actualSig); 92 if (!ok) { 93 System.out.printf("expected: %s%n", expectedSig); 94 System.out.printf("declared: %s%n", actualSig); 95 assertTrue(ok); 96 } 97 } 98 99 // Check that the constructor can be set accessible and that the field x can not 100 void setAccessible() throws Exception { 101 Constructor<?> ctor = c.getDeclaredConstructor(); 102 ctor.setAccessible(true); 103 Field field = c.getField("x"); 104 try { 105 field.setAccessible(true); 106 throw new RuntimeException("InaccessibleObjectException not thrown"); 107 } catch (InaccessibleObjectException e) { 108 // IOE is expected 109 } 110 } 111 112 // Check that the constructor can be set accessible and that the field x can not 113 void trySetAccessible() throws Exception { 114 Constructor<?> ctor = c.getDeclaredConstructor(); 115 assertTrue(ctor.trySetAccessible()); 116 Field field = c.getField("x"); 117 if (field.trySetAccessible()) { 118 throw new RuntimeException("trySetAccessible should not succeed"); 119 } 120 } 121 122 // Check that the class does not have a static method with the name <init> 123 void initFactoryNotMethods() { 124 Method[] methods = c.getDeclaredMethods(); 125 for (Method m : methods) { 126 if (Modifier.isStatic(m.getModifiers())) { 127 assertFalse(m.getName().equals("<init>")); 128 } 129 } 130 } 131 132 static void assertEquals(Object o1, Object o2) { 133 if (o1 == o2 || o1.equals(o2)) 134 return; 135 136 throw new AssertionError(o1 + " != " + o2); 137 } 138 139 static void assertTrue(boolean value) { 140 if (!value) 141 throw new AssertionError("expected true"); 142 } 143 144 static void assertFalse(boolean value) { 145 if (value) 146 throw new AssertionError("expected false"); 147 } 148 }