< prev index next >
hotspot/test/runtime/valhalla/valuetypes/DeriveValueTypeCreation.java
Print this page
@@ -20,18 +20,19 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package runtime.valhalla.valuetypes;
-import java.io.IOException;
-import java.io.RandomAccessFile;
import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import static java.lang.reflect.Modifier.*;
import java.net.URL;
-import java.util.Enumeration;
+import java.util.ArrayList;
+import java.util.HashMap;
+import jdk.experimental.bytecode.*;
import jdk.experimental.value.ValueType;
import jdk.internal.org.objectweb.asm.*;
import static jdk.internal.org.objectweb.asm.Opcodes.*;
@@ -39,27 +40,34 @@
/*
* @test DeriveValueTypeCreation
* @summary Derive Value Type creation test
* @library /test/lib
+ * @compile DeriveValueTypeCreation.java
* @modules java.base/jdk.internal.org.objectweb.asm
* @build runtime.valhalla.valuetypes.ValueCapableClass
* @run main/othervm -Xint -XX:+EnableMVT runtime.valhalla.valuetypes.DeriveValueTypeCreation
* @run main/othervm -Xcomp -XX:+EnableMVT runtime.valhalla.valuetypes.DeriveValueTypeCreation
*/
public class DeriveValueTypeCreation {
public static final String VCC_CLASSNAME = "runtime.valhalla.valuetypes.ValueCapableClass";
+ public static final String DVT_SUFFIX = "$Value";
+
+ public static final int TEST_DEF_CLASS_ACCESS = ACC_SUPER | ACC_PUBLIC | ACC_FINAL;
+ public static final int TEST_DEF_FIELD_ACCESS = ACC_PUBLIC | ACC_FINAL;
+ public static final String OBJECT_CLASS_DESC = "java/lang/Object";
public static void main(String[] args) {
DeriveValueTypeCreation test = new DeriveValueTypeCreation();
test.run();
}
public void run() {
loadAndRunTest();
notValueCapableClasses();
+ loadDvtFirst();
}
void loadAndRunTest() {
Class<?> clazz = null;
try {
@@ -92,11 +100,11 @@
fail("ValueType.sourceClass() failed");
}
// DVT class matches our expectations for the current implementation...
Class<?> vtClass = vt.valueClass();
- if (!vtClass.getName().equals(clazz.getName() + "$Value")) {
+ if (!vtClass.getName().equals(clazz.getName() + DVT_SUFFIX)) {
fail("ValueType.valueClass() failed");
}
if (!vtClass.getSuperclass().getName().equals("java.lang.__Value")) {
fail("ValueType.valueClass() isn't a Value Type class");
}
@@ -112,37 +120,33 @@
fail("ProtectionDomain mismatch");
}
}
void notValueCapableClasses() {
- int vccKlassAccess = ACC_SUPER | ACC_PUBLIC | ACC_FINAL;
- int vccFieldAccess = ACC_PUBLIC | ACC_FINAL;
- String vccSuperClass = "java/lang/Object";
-
- // First a control test to check createTestClass is working
+ // First a control test to check createTestVccClass is working
try {
- Class<?> cls = createTestClass("Control_Case_is_a_VCC", vccKlassAccess, vccSuperClass, "I", vccFieldAccess);
+ Class<?> cls = createTestVccClass("Control_Case_is_a_VCC", TEST_DEF_CLASS_ACCESS, OBJECT_CLASS_DESC, "I", TEST_DEF_FIELD_ACCESS);
checkValueCapableClass(cls);
}
catch (Exception e) {
fail("Control test failed", e);
}
- testFailCase("Not_a_final_class", ACC_SUPER | ACC_PUBLIC, vccSuperClass, "I", vccFieldAccess, "not a final class");
- testFailCase("No_fields", vccKlassAccess, vccSuperClass, null, vccFieldAccess, "has no instance fields");
- testFailCase("Not_final_field", vccKlassAccess, vccSuperClass, "I", ACC_PUBLIC, "contains non-final instance field");
- testFailCase("Super_not_Object", vccKlassAccess, "java/lang/Throwable", "I", vccFieldAccess, "does not derive from Object");
+ testFailCase("Not_a_final_class", ACC_SUPER | ACC_PUBLIC, OBJECT_CLASS_DESC, "I", TEST_DEF_FIELD_ACCESS, "not a final class");
+ testFailCase("No_fields", TEST_DEF_CLASS_ACCESS, OBJECT_CLASS_DESC, null, TEST_DEF_FIELD_ACCESS, "has no instance fields");
+ testFailCase("Not_final_field", TEST_DEF_CLASS_ACCESS, OBJECT_CLASS_DESC, "I", ACC_PUBLIC, "contains non-final instance field");
+ testFailCase("Super_not_Object", TEST_DEF_CLASS_ACCESS, "java/lang/Throwable", "I", TEST_DEF_FIELD_ACCESS, "does not derive from Object");
}
void testFailCase(String clsName,
int klassAccess,
String superKlass,
String fieldType,
int fieldAccess,
String errMsgRequired) {
try {
- createTestClass(clsName, klassAccess, superKlass, fieldType, fieldAccess);
+ createTestVccClass(clsName, klassAccess, superKlass, fieldType, fieldAccess);
fail(clsName + " : failed to fail with Error");
}
catch (ClassNotFoundException cnfe) {
fail(clsName + " : Unexpected ClassNotFoundException", cnfe);
}
@@ -151,40 +155,163 @@
fail(clsName + " : Not the error we were looking for", err);
}
}
}
- Class<?> createTestClass(String name,
+ byte[] createTestVccClassBytes(String name,
+ boolean vccAnnotation) {
+ return createTestVccClassBytes(name, TEST_DEF_CLASS_ACCESS, vccAnnotation, OBJECT_CLASS_DESC, "I", TEST_DEF_FIELD_ACCESS);
+ }
+
+ byte[] createTestVccClassBytes(String name,
int klassAccess,
String superKlass,
String fieldType,
- int fieldAccess) throws ClassNotFoundException {
+ int fieldAccess) {
+ return createTestVccClassBytes(name, klassAccess, true, superKlass, fieldType, fieldAccess);
+ }
+
+ byte[] createTestVccClassBytes(String name,
+ int klassAccess,
+ boolean vccAnnotation,
+ String superKlass,
+ String fieldType,
+ int fieldAccess) {
ClassWriter cw = new ClassWriter(0);
cw.visit(52, klassAccess, name, null, superKlass, null);
+ if (vccAnnotation ) {
cw.visitAnnotation("Ljvm/internal/value/ValueCapableClass;", true);
+ }
if (fieldType != null) {
cw.visitField(fieldAccess, "x", fieldType, null, null);
}
cw.visitEnd();
- return new TestClassLoader(name, cw.toByteArray()).loadClass(name);
+ return cw.toByteArray();
+ }
+
+ Class<?> createTestVccClass(String name,
+ int klassAccess,
+ String superKlass,
+ String fieldType,
+ int fieldAccess) throws ClassNotFoundException {
+ return new TestClassLoader(name,
+ createTestVccClassBytes(name, klassAccess, superKlass, fieldType, fieldAccess)).loadClass(name);
}
class TestClassLoader extends ClassLoader {
- String name;
- byte[] classBytes;
+ HashMap<String, byte[]> namedBytes = new HashMap<>();
+ ArrayList<String> findNames = new ArrayList<String>();
+ TestClassLoader() {}
TestClassLoader(String name, byte[] classBytes) {
- this.name = name;
- this.classBytes = classBytes;
+ addNamedBytes(name, classBytes);
+ }
+
+ void addNamedBytes(String name, byte[] classBytes) {
+ namedBytes.put(name, classBytes);
}
@Override
public Class findClass(String name) throws ClassNotFoundException {
- if (this.name.equals(name)) {
+ byte[] classBytes = null;
+ synchronized (findNames) {
+ findNames.add(name);
+ classBytes = namedBytes.get(name);
+ }
+ if (classBytes != null) {
return defineClass(name, classBytes, 0, classBytes.length);
}
- throw new ClassNotFoundException();
+ throw new ClassNotFoundException(name);
+ }
+
+ public ArrayList<String> getFindNames() {
+ return findNames;
}
}
+ void loadDvtFirst() {
+ try {
+ loadDvtFirstNoVcc();
+ loadDvtFirstNotVcc();
+ loadDvtFirstBadVcc();
+ loadDvtFirstVcc();
+ } catch (Throwable t) {
+ fail("loadDvtFirst failed", t);
+ }
+ }
+
+ void loadDvtFirstNoVcc() throws Throwable {
+ String vccName = "TestNoVcc";
+ try {
+ newDvtUserInstance(vccName, null, false);
+ } catch (NoClassDefFoundError ncdfe) {}
+ try {
+ newDvtUserInstance(vccName, null, true);
+ } catch (NoClassDefFoundError ncdfe) {}
+ }
+
+ void loadDvtFirstNotVcc() throws Throwable {
+ String vccName = "TestNotVcc";
+ byte[] vccBytes = createTestVccClassBytes(vccName, false);
+ try {
+ newDvtUserInstance(vccName, vccBytes, false);
+ } catch (NoClassDefFoundError ncdfe) {}
+ try {
+ newDvtUserInstance(vccName, vccBytes, true);
+ } catch (NoClassDefFoundError ncdfe) {}
+ }
+
+ void loadDvtFirstBadVcc() throws Throwable {
+ String vccName = "TestBadVcc";
+ byte[] vccBytes = createTestVccClassBytes(vccName, TEST_DEF_CLASS_ACCESS,
+ true, OBJECT_CLASS_DESC, "I",
+ ACC_PUBLIC);
+ try {
+ newDvtUserInstance(vccName, vccBytes, false);
+ } catch (IncompatibleClassChangeError icce) {}
+ try {
+ newDvtUserInstance(vccName, vccBytes, true);
+ } catch (IncompatibleClassChangeError icce) {}
+ }
+
+ void loadDvtFirstVcc() throws Throwable {
+ String vccName = "TestValidVcc";
+ byte[] vccBytes = createTestVccClassBytes(vccName, TEST_DEF_CLASS_ACCESS,
+ true, OBJECT_CLASS_DESC, "I",
+ TEST_DEF_FIELD_ACCESS);
+ newDvtUserInstance(vccName, vccBytes, false);
+ newDvtUserInstance(vccName, vccBytes, true);
+ }
+
+ void newDvtUserInstance(String vccName, byte[] vccBytes, boolean withField) throws Throwable {
+ TestClassLoader cl = new TestClassLoader();
+ if (vccBytes != null) {
+ cl.addNamedBytes(vccName, vccBytes);
+ }
+ String dvtUserName = "UseValidDvt";
+ String dvtName = vccName + DVT_SUFFIX;
+ String dvtFieldDesc = "Q" + dvtName + ";";
+ String dvtClassDesc = ";" + dvtFieldDesc;
+ byte[] classBytes = createTestDvtUserClassBytes(dvtUserName, dvtClassDesc, (withField) ? dvtFieldDesc : null);
+ cl.addNamedBytes(dvtUserName, classBytes);
+ try {
+ Class.forName(dvtUserName, true, cl).getDeclaredConstructor().newInstance();
+ } catch (InvocationTargetException ite) { throw ite.getTargetException(); }
+ }
+
+ byte[] createTestDvtUserClassBytes(String className, String dvtDesc, String dvtFieldDesc) {
+ BasicClassBuilder builder = new BasicClassBuilder(className, 53, 1)
+ .withFlags(Flag.ACC_PUBLIC)
+ .withSuperclass("java/lang/Object")
+ .withMethod("<init>", "()V", M ->
+ M.withFlags(Flag.ACC_PUBLIC).withCode(TypedCodeBuilder::new, C ->
+ C
+ .load(0).invokespecial("java/lang/Object", "<init>", "()V", false)
+ .iconst_1().anewarray(dvtDesc).pop()
+ .return_()));
+ if (dvtFieldDesc != null) {
+ builder.withField("dvtField", dvtFieldDesc);
+ }
+ return builder.build();
+ }
}
< prev index next >