8205533: Class.getPackage() fails with InternalError if class is defined to the bootstrap class loader but module is not in the boot layer
Reviewed-by: mchung
--- a/src/java.base/share/classes/jdk/internal/loader/BootLoader.java Sun Jun 24 15:02:08 2018 +0300
+++ b/src/java.base/share/classes/jdk/internal/loader/BootLoader.java Sun Jun 24 16:25:47 2018 +0100
@@ -44,6 +44,7 @@
import jdk.internal.misc.JavaLangAccess;
import jdk.internal.misc.SharedSecrets;
+import jdk.internal.module.Modules;
import jdk.internal.module.ServicesCatalog;
/**
@@ -249,15 +250,16 @@
}
}
+ // return the Module object for the module name. The Module may
+ // in the boot layer or a child layer for the case that the module
+ // is loaded into a running VM
if (mn != null) {
- // named module from runtime image or exploded module
- Optional<Module> om = ModuleLayer.boot().findModule(mn);
- if (!om.isPresent())
- throw new InternalError(mn + " not in boot layer");
- return om.get();
+ String name = mn;
+ return Modules.findLoadedModule(mn)
+ .orElseThrow(() -> new InternalError(name + " not loaded"));
+ } else {
+ return null;
}
-
- return null;
}
/**
--- a/src/java.base/share/classes/jdk/internal/module/Modules.java Sun Jun 24 15:02:08 2018 +0300
+++ b/src/java.base/share/classes/jdk/internal/module/Modules.java Sun Jun 24 16:25:47 2018 +0100
@@ -35,6 +35,7 @@
import java.security.PrivilegedAction;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -249,7 +250,19 @@
}
- // the top-most system layer
- private static ModuleLayer topLayer;
+ /**
+ * Finds the module with the given name in the boot layer or any child
+ * layers created to load the "java.instrument" or "jdk.management.agent"
+ * modules into a running VM.
+ */
+ public static Optional<Module> findLoadedModule(String name) {
+ ModuleLayer top = topLayer;
+ if (top == null)
+ top = ModuleLayer.boot();
+ return top.findModule(name);
+ }
+
+ // the top-most layer
+ private static volatile ModuleLayer topLayer;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/Class/GetPackageBootLoaderChildLayer.java Sun Jun 24 16:25:47 2018 +0100
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @modules jdk.attach
+ * @run main/othervm --limit-modules jdk.attach -Djdk.attach.allowAttachSelf
+ * GetPackageBootLoaderChildLayer
+ * @summary Exercise Class.getPackage on a class defined to the boot loader
+ * but in a module that is in a child layer rather than the boot layer
+ */
+
+import com.sun.tools.attach.VirtualMachine;
+
+public class GetPackageBootLoaderChildLayer {
+ public static void main(String[] args) throws Exception {
+ // ensure that the java.management module is not in the boot layer
+ ModuleLayer.boot().findModule("java.management").ifPresent(m -> {
+ throw new RuntimeException("java.management loaded!!!");
+ });
+
+ // start local JMX agent via the attach mechanism
+ String vmid = "" + ProcessHandle.current().pid();
+ VirtualMachine vm = VirtualMachine.attach(vmid);
+ vm.startLocalManagementAgent();
+
+ // check layer, class loader, and Package object
+ Class<?> clazz = Class.forName("javax.management.MXBean");
+ if (clazz.getModule().getLayer() == ModuleLayer.boot())
+ throw new RuntimeException("Module is in boot layer!!!");
+ ClassLoader loader = clazz.getClassLoader();
+ if (loader != null)
+ throw new RuntimeException("Unexpected class loader: " + loader);
+ Package p = clazz.getPackage();
+ if (!p.getName().equals("javax.management"))
+ throw new RuntimeException("Unexpected package " + p);
+ }
+}