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 -XX:+EnableMVT runtime.valhalla.valuetypes.DeriveValueTypeCreation 47 * @run main/othervm -Xcomp -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/ValueCapableClass;", 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 } | 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.lang.reflect.Field; 26 import java.lang.reflect.InvocationTargetException; 27 import java.lang.reflect.Method; 28 import static java.lang.reflect.Modifier.*; 29 import java.net.URL; 30 import java.util.ArrayList; 31 import java.util.HashMap; 32 33 import jdk.experimental.bytecode.*; 34 import jdk.experimental.value.ValueType; 35 36 import jdk.internal.org.objectweb.asm.*; 37 import static jdk.internal.org.objectweb.asm.Opcodes.*; 38 39 import static jdk.test.lib.Asserts.*; 40 41 /* 42 * @test DeriveValueTypeCreation 43 * @summary Derive Value Type creation test 44 * @library /test/lib 45 * @compile DeriveValueTypeCreation.java 46 * @modules java.base/jdk.internal.org.objectweb.asm 47 * @build runtime.valhalla.valuetypes.ValueCapableClass 48 * @run main/othervm -Xint -XX:+EnableMVT runtime.valhalla.valuetypes.DeriveValueTypeCreation 49 * @run main/othervm -Xcomp -XX:+EnableMVT runtime.valhalla.valuetypes.DeriveValueTypeCreation 50 */ 51 public class DeriveValueTypeCreation { 52 53 public static final String VCC_CLASSNAME = "runtime.valhalla.valuetypes.ValueCapableClass"; 54 public static final String DVT_SUFFIX = "$Value"; 55 56 public static final int TEST_DEF_CLASS_ACCESS = ACC_SUPER | ACC_PUBLIC | ACC_FINAL; 57 public static final int TEST_DEF_FIELD_ACCESS = ACC_PUBLIC | ACC_FINAL; 58 public static final String OBJECT_CLASS_DESC = "java/lang/Object"; 59 60 public static void main(String[] args) { 61 DeriveValueTypeCreation test = new DeriveValueTypeCreation(); 62 test.run(); 63 } 64 65 public void run() { 66 loadAndRunTest(); 67 notValueCapableClasses(); 68 loadDvtFirst(); 69 } 70 71 void loadAndRunTest() { 72 Class<?> clazz = null; 73 try { 74 clazz = Class.forName(VCC_CLASSNAME, true, getClass().getClassLoader()); 75 clazz.getDeclaredMethod("test").invoke(null); 76 } 77 catch (ClassNotFoundException cnfe) { fail("VCC class missing", cnfe); } 78 catch (NoSuchMethodException nsme) { fail("VCC test method missing", nsme); } 79 catch (Throwable t) { fail("Failed to invoke VCC.test()", t); } 80 81 checkValueCapableClass(clazz); 82 } 83 84 void checkValueCapableClass(Class<?> clazz) { 85 if (!ValueType.classHasValueType(clazz)) { 86 fail("!classHasValueType: " + clazz); 87 } 88 89 ValueType<?> vt = ValueType.forClass(clazz); 90 if (vt == null) { 91 fail("ValueType.forClass failed"); 92 } 93 94 System.out.println("ValueType: " + vt); 95 96 if (vt.boxClass() != clazz) { 97 fail("ValueType.boxClass() failed"); 98 } 99 if (vt.sourceClass() != clazz) { 100 fail("ValueType.sourceClass() failed"); 101 } 102 103 // DVT class matches our expectations for the current implementation... 104 Class<?> vtClass = vt.valueClass(); 105 if (!vtClass.getName().equals(clazz.getName() + DVT_SUFFIX)) { 106 fail("ValueType.valueClass() failed"); 107 } 108 if (!vtClass.getSuperclass().getName().equals("java.lang.__Value")) { 109 fail("ValueType.valueClass() isn't a Value Type class"); 110 } 111 112 // Exercise "Class.getSimpleName()", we've cause problems with it before 113 String sn = vtClass.getSimpleName(); 114 System.out.println("SimpleName: " + sn); 115 116 if (clazz.getClassLoader() != vtClass.getClassLoader()) { 117 fail("ClassLoader mismatch"); 118 } 119 if (clazz.getProtectionDomain() != vtClass.getProtectionDomain()) { 120 fail("ProtectionDomain mismatch"); 121 } 122 } 123 124 void notValueCapableClasses() { 125 // First a control test to check createTestVccClass is working 126 try { 127 Class<?> cls = createTestVccClass("Control_Case_is_a_VCC", TEST_DEF_CLASS_ACCESS, OBJECT_CLASS_DESC, "I", TEST_DEF_FIELD_ACCESS); 128 checkValueCapableClass(cls); 129 } 130 catch (Exception e) { 131 fail("Control test failed", e); 132 } 133 134 testFailCase("Not_a_final_class", ACC_SUPER | ACC_PUBLIC, OBJECT_CLASS_DESC, "I", TEST_DEF_FIELD_ACCESS, "not a final class"); 135 testFailCase("No_fields", TEST_DEF_CLASS_ACCESS, OBJECT_CLASS_DESC, null, TEST_DEF_FIELD_ACCESS, "has no instance fields"); 136 testFailCase("Not_final_field", TEST_DEF_CLASS_ACCESS, OBJECT_CLASS_DESC, "I", ACC_PUBLIC, "contains non-final instance field"); 137 testFailCase("Super_not_Object", TEST_DEF_CLASS_ACCESS, "java/lang/Throwable", "I", TEST_DEF_FIELD_ACCESS, "does not derive from Object"); 138 } 139 140 void testFailCase(String clsName, 141 int klassAccess, 142 String superKlass, 143 String fieldType, 144 int fieldAccess, 145 String errMsgRequired) { 146 try { 147 createTestVccClass(clsName, klassAccess, superKlass, fieldType, fieldAccess); 148 fail(clsName + " : failed to fail with Error"); 149 } 150 catch (ClassNotFoundException cnfe) { 151 fail(clsName + " : Unexpected ClassNotFoundException", cnfe); 152 } 153 catch (Error err) { 154 if (!err.getMessage().contains(errMsgRequired)) { 155 fail(clsName + " : Not the error we were looking for", err); 156 } 157 } 158 } 159 160 byte[] createTestVccClassBytes(String name, 161 boolean vccAnnotation) { 162 return createTestVccClassBytes(name, TEST_DEF_CLASS_ACCESS, vccAnnotation, OBJECT_CLASS_DESC, "I", TEST_DEF_FIELD_ACCESS); 163 } 164 165 byte[] createTestVccClassBytes(String name, 166 int klassAccess, 167 String superKlass, 168 String fieldType, 169 int fieldAccess) { 170 return createTestVccClassBytes(name, klassAccess, true, superKlass, fieldType, fieldAccess); 171 } 172 173 byte[] createTestVccClassBytes(String name, 174 int klassAccess, 175 boolean vccAnnotation, 176 String superKlass, 177 String fieldType, 178 int fieldAccess) { 179 ClassWriter cw = new ClassWriter(0); 180 cw.visit(52, klassAccess, name, null, superKlass, null); 181 if (vccAnnotation ) { 182 cw.visitAnnotation("Ljvm/internal/value/ValueCapableClass;", true); 183 } 184 if (fieldType != null) { 185 cw.visitField(fieldAccess, "x", fieldType, null, null); 186 } 187 cw.visitEnd(); 188 return cw.toByteArray(); 189 } 190 191 Class<?> createTestVccClass(String name, 192 int klassAccess, 193 String superKlass, 194 String fieldType, 195 int fieldAccess) throws ClassNotFoundException { 196 return new TestClassLoader(name, 197 createTestVccClassBytes(name, klassAccess, superKlass, fieldType, fieldAccess)).loadClass(name); 198 } 199 200 class TestClassLoader extends ClassLoader { 201 202 HashMap<String, byte[]> namedBytes = new HashMap<>(); 203 ArrayList<String> findNames = new ArrayList<String>(); 204 205 TestClassLoader() {} 206 TestClassLoader(String name, byte[] classBytes) { 207 addNamedBytes(name, classBytes); 208 } 209 210 void addNamedBytes(String name, byte[] classBytes) { 211 namedBytes.put(name, classBytes); 212 } 213 214 @Override 215 public Class findClass(String name) throws ClassNotFoundException { 216 byte[] classBytes = null; 217 synchronized (findNames) { 218 findNames.add(name); 219 classBytes = namedBytes.get(name); 220 } 221 if (classBytes != null) { 222 return defineClass(name, classBytes, 0, classBytes.length); 223 } 224 throw new ClassNotFoundException(name); 225 } 226 227 public ArrayList<String> getFindNames() { 228 return findNames; 229 } 230 } 231 232 void loadDvtFirst() { 233 try { 234 loadDvtFirstNoVcc(); 235 loadDvtFirstNotVcc(); 236 loadDvtFirstBadVcc(); 237 loadDvtFirstVcc(); 238 } catch (Throwable t) { 239 fail("loadDvtFirst failed", t); 240 } 241 } 242 243 void loadDvtFirstNoVcc() throws Throwable { 244 String vccName = "TestNoVcc"; 245 try { 246 newDvtUserInstance(vccName, null, false); 247 } catch (NoClassDefFoundError ncdfe) {} 248 try { 249 newDvtUserInstance(vccName, null, true); 250 } catch (NoClassDefFoundError ncdfe) {} 251 } 252 253 void loadDvtFirstNotVcc() throws Throwable { 254 String vccName = "TestNotVcc"; 255 byte[] vccBytes = createTestVccClassBytes(vccName, false); 256 try { 257 newDvtUserInstance(vccName, vccBytes, false); 258 } catch (NoClassDefFoundError ncdfe) {} 259 try { 260 newDvtUserInstance(vccName, vccBytes, true); 261 } catch (NoClassDefFoundError ncdfe) {} 262 } 263 264 void loadDvtFirstBadVcc() throws Throwable { 265 String vccName = "TestBadVcc"; 266 byte[] vccBytes = createTestVccClassBytes(vccName, TEST_DEF_CLASS_ACCESS, 267 true, OBJECT_CLASS_DESC, "I", 268 ACC_PUBLIC); 269 try { 270 newDvtUserInstance(vccName, vccBytes, false); 271 } catch (IncompatibleClassChangeError icce) {} 272 try { 273 newDvtUserInstance(vccName, vccBytes, true); 274 } catch (IncompatibleClassChangeError icce) {} 275 } 276 277 void loadDvtFirstVcc() throws Throwable { 278 String vccName = "TestValidVcc"; 279 byte[] vccBytes = createTestVccClassBytes(vccName, TEST_DEF_CLASS_ACCESS, 280 true, OBJECT_CLASS_DESC, "I", 281 TEST_DEF_FIELD_ACCESS); 282 newDvtUserInstance(vccName, vccBytes, false); 283 newDvtUserInstance(vccName, vccBytes, true); 284 } 285 286 void newDvtUserInstance(String vccName, byte[] vccBytes, boolean withField) throws Throwable { 287 TestClassLoader cl = new TestClassLoader(); 288 if (vccBytes != null) { 289 cl.addNamedBytes(vccName, vccBytes); 290 } 291 String dvtUserName = "UseValidDvt"; 292 String dvtName = vccName + DVT_SUFFIX; 293 String dvtFieldDesc = "Q" + dvtName + ";"; 294 String dvtClassDesc = ";" + dvtFieldDesc; 295 byte[] classBytes = createTestDvtUserClassBytes(dvtUserName, dvtClassDesc, (withField) ? dvtFieldDesc : null); 296 cl.addNamedBytes(dvtUserName, classBytes); 297 try { 298 Class.forName(dvtUserName, true, cl).getDeclaredConstructor().newInstance(); 299 } catch (InvocationTargetException ite) { throw ite.getTargetException(); } 300 } 301 302 byte[] createTestDvtUserClassBytes(String className, String dvtDesc, String dvtFieldDesc) { 303 BasicClassBuilder builder = new BasicClassBuilder(className, 53, 1) 304 .withFlags(Flag.ACC_PUBLIC) 305 .withSuperclass("java/lang/Object") 306 .withMethod("<init>", "()V", M -> 307 M.withFlags(Flag.ACC_PUBLIC).withCode(TypedCodeBuilder::new, C -> 308 C 309 .load(0).invokespecial("java/lang/Object", "<init>", "()V", false) 310 .iconst_1().anewarray(dvtDesc).pop() 311 .return_())); 312 if (dvtFieldDesc != null) { 313 builder.withField("dvtField", dvtFieldDesc); 314 } 315 return builder.build(); 316 } 317 } |