jdk/src/java.base/share/classes/java/lang/SecurityManager.java
changeset 45004 ea3137042a61
parent 44545 83b611b88ac8
child 45658 0c39b586b8fa
--- a/jdk/src/java.base/share/classes/java/lang/SecurityManager.java	Mon Apr 24 13:43:34 2017 +0800
+++ b/jdk/src/java.base/share/classes/java/lang/SecurityManager.java	Thu May 04 07:26:55 2017 +0000
@@ -25,10 +25,10 @@
 
 package java.lang;
 
-import java.lang.RuntimePermission;
 import java.lang.module.ModuleDescriptor;
 import java.lang.module.ModuleDescriptor.Exports;
 import java.lang.module.ModuleDescriptor.Opens;
+import java.lang.module.ModuleReference;
 import java.lang.reflect.Member;
 import java.io.FileDescriptor;
 import java.io.File;
@@ -42,12 +42,15 @@
 import java.security.Security;
 import java.security.SecurityPermission;
 import java.util.HashSet;
+import java.util.Map;
 import java.util.Objects;
 import java.util.PropertyPermission;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.stream.Collectors;
-import java.util.stream.Stream;
 
+import jdk.internal.module.ModuleBootstrap;
+import jdk.internal.module.ModuleLoaderMap;
 import jdk.internal.reflect.CallerSensitive;
 import sun.security.util.SecurityConstants;
 
@@ -1431,29 +1434,29 @@
         return packages;
     }
 
-    // The non-exported packages of the modules in the boot layer that are
-    // loaded by the platform class loader or its ancestors. A non-exported
-    // package is a package that either is not exported at all by its containing
-    // module or is exported in a qualified fashion by its containing module.
-    private static final Set<String> nonExportedPkgs;
-
+    // The non-exported packages in modules defined to the boot or platform
+    // class loaders. A non-exported package is a package that is not exported
+    // or is only exported to specific modules.
+    private static final Map<String, Boolean> nonExportedPkgs = new ConcurrentHashMap<>();
     static {
-        // Get the modules in the boot layer
-        Stream<Module> bootLayerModules = ModuleLayer.boot().modules().stream();
+        addNonExportedPackages(ModuleLayer.boot());
+    }
 
-        // Filter out the modules loaded by the boot or platform loader
-        PrivilegedAction<Set<Module>> pa = () ->
-            bootLayerModules.filter(SecurityManager::isBootOrPlatformModule)
-                            .collect(Collectors.toSet());
-        Set<Module> modules = AccessController.doPrivileged(pa);
+    /**
+     * Record the non-exported packages of the modules in the given layer
+     */
+    static void addNonExportedPackages(ModuleLayer layer) {
+        Set<String> bootModules = ModuleLoaderMap.bootModules();
+        Set<String> platformModules = ModuleLoaderMap.platformModules();
+        layer.modules().stream()
+                .map(Module::getDescriptor)
+                .filter(md -> bootModules.contains(md.name())
+                        || platformModules.contains(md.name()))
+                .map(SecurityManager::nonExportedPkgs)
+                .flatMap(Set::stream)
+                .forEach(pn -> nonExportedPkgs.put(pn, Boolean.TRUE));
+    }
 
-        // Filter out the non-exported packages
-        nonExportedPkgs = modules.stream()
-                                 .map(Module::getDescriptor)
-                                 .map(SecurityManager::nonExportedPkgs)
-                                 .flatMap(Set::stream)
-                                 .collect(Collectors.toSet());
-    }
 
     /**
      * Called by java.security.Security
@@ -1468,14 +1471,6 @@
     }
 
     /**
-     * Returns true if the module's loader is the boot or platform loader.
-     */
-    private static boolean isBootOrPlatformModule(Module m) {
-        return m.getClassLoader() == null ||
-               m.getClassLoader() == ClassLoader.getPlatformClassLoader();
-    }
-
-    /**
      * Returns the non-exported packages of the specified module.
      */
     private static Set<String> nonExportedPkgs(ModuleDescriptor md) {
@@ -1535,7 +1530,7 @@
         Objects.requireNonNull(pkg, "package name can't be null");
 
         // check if pkg is not exported to all modules
-        if (nonExportedPkgs.contains(pkg)) {
+        if (nonExportedPkgs.containsKey(pkg)) {
             checkPermission(
                 new RuntimePermission("accessClassInPackage." + pkg));
             return;
@@ -1634,7 +1629,7 @@
         Objects.requireNonNull(pkg, "package name can't be null");
 
         // check if pkg is not exported to all modules
-        if (nonExportedPkgs.contains(pkg)) {
+        if (nonExportedPkgs.containsKey(pkg)) {
             checkPermission(
                 new RuntimePermission("defineClassInPackage." + pkg));
             return;