1 /* 2 * Copyright (c) 2017, 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 package runtime.valhalla.valuetypes; 24 25 import java.io.IOException; 26 import java.io.RandomAccessFile; 27 import java.lang.reflect.Field; 28 import java.lang.reflect.Method; 29 import static java.lang.reflect.Modifier.*; 30 import java.net.URL; 31 import java.util.Enumeration; 32 33 import jdk.experimental.value.ValueType; 34 35 import jdk.internal.org.objectweb.asm.*; 36 import static jdk.internal.org.objectweb.asm.Opcodes.*; 37 38 import static jdk.test.lib.Asserts.*; 39 40 /* 41 * @test DeriveValueTypeCreation 42 * @summary Derive Value Type creation test 43 * @library /test/lib 44 * @modules java.base/jdk.internal.org.objectweb.asm 45 * @build runtime.valhalla.valuetypes.ValueCapableClass 46 * @run main/othervm -Xint -noverify -XX:+EnableMVT runtime.valhalla.valuetypes.DeriveValueTypeCreation 47 * @run main/othervm -Xcomp -noverify -XX:+EnableMVT runtime.valhalla.valuetypes.DeriveValueTypeCreation 48 */ 49 public class DeriveValueTypeCreation { 50 51 public static final String VCC_CLASSNAME = "runtime.valhalla.valuetypes.ValueCapableClass"; 52 53 public static void main(String[] args) { 54 DeriveValueTypeCreation test = new DeriveValueTypeCreation(); 55 test.run(); 56 } 57 58 public void run() { 59 loadAndRunTest(); 60 notValueCapableClasses(); 61 } 62 63 void loadAndRunTest() { 64 Class<?> clazz = null; 65 try { 66 clazz = Class.forName(VCC_CLASSNAME, true, getClass().getClassLoader()); 67 clazz.getDeclaredMethod("test").invoke(null); 68 } 69 catch (ClassNotFoundException cnfe) { fail("VCC class missing", cnfe); } 70 catch (NoSuchMethodException nsme) { fail("VCC test method missing", nsme); } 71 catch (Throwable t) { fail("Failed to invoke VCC.test()", t); } 72 73 checkValueCapableClass(clazz); 74 } 75 76 void checkValueCapableClass(Class<?> clazz) { 77 if (!ValueType.classHasValueType(clazz)) { 78 fail("!classHasValueType: " + clazz); 79 } 80 81 ValueType<?> vt = ValueType.forClass(clazz); 82 if (vt == null) { 83 fail("ValueType.forClass failed"); 84 } 85 86 System.out.println("ValueType: " + vt); 87 88 if (vt.boxClass() != clazz) { 89 fail("ValueType.boxClass() failed"); 90 } 91 if (vt.sourceClass() != clazz) { 92 fail("ValueType.sourceClass() failed"); 93 } 94 95 // DVT class matches our expectations for the current implementation... 96 Class<?> vtClass = vt.valueClass(); 97 if (!vtClass.getName().equals(clazz.getName() + "$Value")) { 98 fail("ValueType.valueClass() failed"); 99 } 100 if (!vtClass.getSuperclass().getName().equals("java.lang.__Value")) { 101 fail("ValueType.valueClass() isn't a Value Type class"); 102 } 103 104 // Exercise "Class.getSimpleName()", we've cause problems with it before 105 String sn = vtClass.getSimpleName(); 106 System.out.println("SimpleName: " + sn); 107 108 if (clazz.getClassLoader() != vtClass.getClassLoader()) { 109 fail("ClassLoader mismatch"); 110 } 111 if (clazz.getProtectionDomain() != vtClass.getProtectionDomain()) { 112 fail("ProtectionDomain mismatch"); 113 } 114 } 115 116 void notValueCapableClasses() { 117 int vccKlassAccess = ACC_SUPER | ACC_PUBLIC | ACC_FINAL; 118 int vccFieldAccess = ACC_PUBLIC | ACC_FINAL; 119 String vccSuperClass = "java/lang/Object"; 120 121 // First a control test to check createTestClass is working 122 try { 123 Class<?> cls = createTestClass("Control_Case_is_a_VCC", vccKlassAccess, vccSuperClass, "I", vccFieldAccess); 124 checkValueCapableClass(cls); 125 } 126 catch (Exception e) { 127 fail("Control test failed", e); 128 } 129 130 testFailCase("Not_a_final_class", ACC_SUPER | ACC_PUBLIC, vccSuperClass, "I", vccFieldAccess, "not a final class"); 131 testFailCase("No_fields", vccKlassAccess, vccSuperClass, null, vccFieldAccess, "has no instance fields"); 132 testFailCase("Not_final_field", vccKlassAccess, vccSuperClass, "I", ACC_PUBLIC, "contains non-final instance field"); 133 testFailCase("Super_not_Object", vccKlassAccess, "java/lang/Throwable", "I", vccFieldAccess, "does not derive from Object"); 134 } 135 136 void testFailCase(String clsName, 137 int klassAccess, 138 String superKlass, 139 String fieldType, 140 int fieldAccess, 141 String errMsgRequired) { 142 try { 143 createTestClass(clsName, klassAccess, superKlass, fieldType, fieldAccess); 144 fail(clsName + " : failed to fail with Error"); 145 } 146 catch (ClassNotFoundException cnfe) { 147 fail(clsName + " : Unexpected ClassNotFoundException", cnfe); 148 } 149 catch (Error err) { 150 if (!err.getMessage().contains(errMsgRequired)) { 151 fail(clsName + " : Not the error we were looking for", err); 152 } 153 } 154 } 155 156 Class<?> createTestClass(String name, 157 int klassAccess, 158 String superKlass, 159 String fieldType, 160 int fieldAccess) throws ClassNotFoundException { 161 ClassWriter cw = new ClassWriter(0); 162 cw.visit(52, klassAccess, name, null, superKlass, null); 163 cw.visitAnnotation("Ljvm/internal/value/DeriveValueType;", true); 164 if (fieldType != null) { 165 cw.visitField(fieldAccess, "x", fieldType, null, null); 166 } 167 cw.visitEnd(); 168 return new TestClassLoader(name, cw.toByteArray()).loadClass(name); 169 } 170 171 class TestClassLoader extends ClassLoader { 172 173 String name; 174 byte[] classBytes; 175 176 TestClassLoader(String name, byte[] classBytes) { 177 this.name = name; 178 this.classBytes = classBytes; 179 } 180 181 @Override 182 public Class findClass(String name) throws ClassNotFoundException { 183 if (this.name.equals(name)) { 184 return defineClass(name, classBytes, 0, classBytes.length); 185 } 186 throw new ClassNotFoundException(); 187 } 188 } 189 190 }