changeset 14167:4b16ae395bbe

Expand GetModuleTest to VM anonymous classes
author alanb
date Thu, 01 Oct 2015 11:16:01 +0100
parents 8d3fcb58b82c
children 2b6cb5de27d5
files src/java.base/share/classes/jdk/internal/misc/BuiltinClassLoader.java test/java/lang/Class/GetModuleTest.java
diffstat 2 files changed, 93 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.base/share/classes/jdk/internal/misc/BuiltinClassLoader.java	Thu Oct 01 08:59:23 2015 +0100
+++ b/src/java.base/share/classes/jdk/internal/misc/BuiltinClassLoader.java	Thu Oct 01 11:16:01 2015 +0100
@@ -561,21 +561,27 @@
      * @param c a Class defined by this class loader
      */
     Package definePackage(Class<?> c) {
-        Module m = c.getModule();
-        String cn = c.getName();
-        int pos = cn.lastIndexOf('.');
-        if (pos < 0 && m.isNamed()) {
-            throw new InternalError("unnamed package in named module "
-                                    + m.getName());
+        String pn;
+        if (c.isPrimitive()) {
+            pn = "";
+        } else {
+            Module m = c.getModule();
+            String cn = c.getName();
+            int pos = cn.lastIndexOf('.');
+            if (pos < 0 && m.isNamed()) {
+                throw new InternalError("unnamed package in named module "
+                                        + m.getName());
+            }
+            pn = (pos != -1) ? cn.substring(0, pos) : "";
         }
-        String pn = (pos != -1) ? cn.substring(0, pos) : "";
+
         Package p = getDefinedPackage(pn);
-
         if (p == null) {
             URL url = null;
 
             // The given class may be dynamically generated and
             // its package is not in packageToModule map.
+            Module m = c.getModule();
             if (m.isNamed()) {
                 ModuleReference mref = nameToModule.get(m.getName());
                 if (mref != null) {
--- a/test/java/lang/Class/GetModuleTest.java	Thu Oct 01 08:59:23 2015 +0100
+++ b/test/java/lang/Class/GetModuleTest.java	Thu Oct 01 11:16:01 2015 +0100
@@ -24,23 +24,40 @@
 /*
  * @test
  * @summary Exercise Class#getModule
+ * @modules java.base/jdk.internal.org.objectweb.asm
  * @run testng GetModuleTest
  */
 
 import java.awt.Component;
+import java.lang.reflect.Field;
 import java.lang.reflect.Module;
 
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import static jdk.internal.org.objectweb.asm.Opcodes.*;
+import sun.misc.Unsafe;
+
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
-
 import static org.testng.Assert.*;
 
 public class GetModuleTest {
 
+    static final Unsafe U;
+    static {
+        try {
+            Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
+            theUnsafe.setAccessible(true);
+            U = (Unsafe) theUnsafe.get(null);
+        } catch (Exception e) {
+            throw new AssertionError(e);
+        }
+    }
+
     private static final Module TEST_MODULE = GetModuleTest.class.getModule();
 
-    @DataProvider(name = "samples")
-    public Object[][] sampleData() {
+
+    @DataProvider(name = "testclasses")
+    public Object[][] testClasses() {
         return new Object[][] {
 
             // unnamed module
@@ -55,6 +72,7 @@
             { int[].class,          "java.base" },
             { int[][].class,        "java.base" },
             { void.class,           "java.base" },
+
             { Object.class,         "java.base" },
             { Object[].class,       "java.base" },
             { Object[][].class,     "java.base" },
@@ -64,7 +82,7 @@
         };
     }
 
-    @Test(dataProvider = "samples")
+    @Test(dataProvider = "testClasses")
     public void testGetModule(Class<?> type, String expected) {
         Module m = type.getModule();
         assertNotNull(m);
@@ -74,4 +92,61 @@
             assertEquals(m.getName(), expected);
         }
     }
+
+
+    @DataProvider(name = "hostclasses")
+    public Object[][] hostClasses() {
+        return new Object[][] {
+
+            { GetModuleTest.class,      null },
+            { GetModuleTest[].class,    null },
+            { Object.class,             null },
+            { Object[].class,           null },
+            { Component.class,          null },
+            { Component[].class,        null },
+
+        };
+    }
+
+    /**
+     * Exercise Class::getModule on VM anonymous classes
+     */
+    @Test(dataProvider = "hostclasses")
+    public void testGetModuleOnVMAnonymousClass(Class<?> hostClass, String ignore) {
+
+        // choose a class name in the same package as the host class
+        String prefix = packageName(hostClass);
+        if (prefix.length() > 0)
+            prefix = prefix.replace('.', '/') + "/";
+        String className = prefix + "Anon";
+
+        // create the class
+        String superName = "java/lang/Object";
+        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS
+                                         + ClassWriter.COMPUTE_FRAMES);
+        cw.visit(V1_8, ACC_PUBLIC + ACC_FINAL + ACC_SUPER,
+                 className, null, superName, null);
+        byte[] classBytes = cw.toByteArray();
+        int cpPoolSize = constantPoolSize(classBytes);
+        Class<?> anonClass
+            = U.defineAnonymousClass(hostClass, classBytes, new Object[cpPoolSize]);
+
+        assertTrue(anonClass.getModule() == hostClass.getModule());
+    }
+
+    private static String packageName(Class<?> c) {
+        if (c.isArray()) {
+            return packageName(c.getComponentType());
+        } else {
+            String name = c.getName();
+            int dot = name.lastIndexOf('.');
+            if (dot == -1) return "";
+            return name.substring(0, dot);
+        }
+    }
+
+    private static int constantPoolSize(byte[] classFile) {
+        return ((classFile[8] & 0xFF) << 8) | (classFile[9] & 0xFF);
+    }
+
 }