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