1 /* 2 * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 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 24 /* 25 * @test 26 * @summary class p1.c1 defined in m1x tries to access p2.c2 defined in unnamed module. 27 * @library /test/lib 28 * @modules java.base/jdk.internal.misc 29 * @modules java.base/jdk.internal.module 30 * @compile myloaders/MyDiffClassLoader.java 31 * @compile p2/c2.java 32 * @compile p1/c1.java 33 * @compile p1/c1ReadEdgeDiffLoader.java 34 * @compile p1/c1Loose.java 35 * @run main/othervm -Xbootclasspath/a:. DiffCL_Umod 36 */ 37 38 import static jdk.test.lib.Asserts.*; 39 40 import java.lang.module.Configuration; 41 import java.lang.module.ModuleDescriptor; 42 import java.lang.module.ModuleFinder; 43 import java.util.HashMap; 44 import java.util.Map; 45 import java.util.Set; 46 import myloaders.MyDiffClassLoader; 47 48 // 49 // ClassLoader1 --> defines m1x --> packages p1 50 // package p1 in m1x is exported unqualifiedly 51 // 52 // class p1.c1 defined in m1x tries to access p2.c2 defined in 53 // in unnamed module. 54 // 55 // Three access attempts occur in this test: 56 // 1. The first access is not allowed because a strict module 57 // cannot read an unnamed module. 58 // 2. In this scenario a strict module establishes readability 59 // to the particular unnamed module it is trying to access. 60 // Access is allowed. 61 // 3. Module m1x in the test_looseModuleLayer() method 62 // is transitioned to a loose module, access 63 // to all unnamed modules is allowed. 64 // 65 public class DiffCL_Umod { 66 67 // Create layers over the boot layer to test different 68 // accessing scenarios of a named module to an unnamed module. 69 70 // Module m1x is a strict module and has not established 71 // readability to an unnamed module that p2.c2 is defined in. 72 public void test_strictModuleLayer() throws Throwable { 73 74 // Define module: m1x 75 // Can read: java.base 76 // Packages: p1 77 // Packages exported: p1 is exported unqualifiedly 78 ModuleDescriptor descriptor_m1x = 79 ModuleDescriptor.newModule("m1x") 80 .requires("java.base") 81 .exports("p1") 82 .build(); 83 84 // Set up a ModuleFinder containing all modules for this layer. 85 ModuleFinder finder = ModuleLibrary.of(descriptor_m1x); 86 87 // Resolves "m1x" 88 Configuration cf = ModuleLayer.boot() 89 .configuration() 90 .resolve(finder, ModuleFinder.of(), Set.of("m1x")); 91 92 MyDiffClassLoader.loader1 = new MyDiffClassLoader(); 93 MyDiffClassLoader.loader2 = new MyDiffClassLoader(); 94 95 // map module m1x to class loader. 96 // class c2 will be loaded in an unnamed module/loader2 97 // to achieve differing class loaders. 98 Map<String, ClassLoader> map = new HashMap<>(); 99 map.put("m1x", MyDiffClassLoader.loader1); 100 101 // Create layer that contains m1x 102 ModuleLayer layer = ModuleLayer.boot().defineModules(cf, map::get); 103 104 assertTrue(layer.findLoader("m1x") == MyDiffClassLoader.loader1); 105 assertTrue(layer.findLoader("java.base") == null); 106 107 // now use the same loader to load class p1.c1 108 Class p1_c1_class = MyDiffClassLoader.loader1.loadClass("p1.c1"); 109 110 // Attempt access 111 try { 112 p1_c1_class.newInstance(); 113 throw new RuntimeException("Test Failed, strict module m1x should not be able " + 114 "to access public type p2.c2 defined in unnamed module"); 115 } catch (IllegalAccessError e) { 116 } 117 } 118 119 // Module m1x is a strict module and has established 120 // readability to an unnamed module that p2.c2 is defined in. 121 public void test_strictModuleUnnamedReadableLayer() throws Throwable { 122 123 // Define module: m1x 124 // Can read: java.base 125 // Packages: p1 126 // Packages exported: p1 is exported unqualifiedly 127 ModuleDescriptor descriptor_m1x = 128 ModuleDescriptor.newModule("m1x") 129 .requires("java.base") 130 .exports("p1") 131 .build(); 132 133 // Set up a ModuleFinder containing all modules for this layer. 134 ModuleFinder finder = ModuleLibrary.of(descriptor_m1x); 135 136 // Resolves "m1x" 137 Configuration cf = ModuleLayer.boot() 138 .configuration() 139 .resolve(finder, ModuleFinder.of(), Set.of("m1x")); 140 141 MyDiffClassLoader.loader1 = new MyDiffClassLoader(); 142 MyDiffClassLoader.loader2 = new MyDiffClassLoader(); 143 144 // map module m1x to class loader. 145 // class c2 will be loaded in an unnamed module/loader2 146 // to achieve differing class loaders. 147 Map<String, ClassLoader> map = new HashMap<>(); 148 map.put("m1x", MyDiffClassLoader.loader1); 149 150 // Create layer that contains m1x 151 ModuleLayer layer = ModuleLayer.boot().defineModules(cf, map::get); 152 153 assertTrue(layer.findLoader("m1x") == MyDiffClassLoader.loader1); 154 assertTrue(layer.findLoader("java.base") == null); 155 156 // now use the same loader to load class p1.c1ReadEdgeDiffLoader 157 Class p1_c1_class = MyDiffClassLoader.loader1.loadClass("p1.c1ReadEdgeDiffLoader"); 158 159 try { 160 // Read edge between m1x and the unnamed module that loads p2.c2 is established in 161 // c1ReadEdgeDiffLoader's ctor before attempting access. 162 p1_c1_class.newInstance(); 163 } catch (IllegalAccessError e) { 164 throw new RuntimeException("Test Failed, module m1x has established readability to p2/c2 loader's " + 165 "unnamed module, access should be allowed: " + e.getMessage()); 166 } 167 } 168 169 // Module m1x is a loose module and thus can read all unnamed modules. 170 public void test_looseModuleLayer() throws Throwable { 171 172 // Define module: m1x 173 // Can read: java.base 174 // Packages: p1 175 // Packages exported: p1 is exported unqualifiedly 176 ModuleDescriptor descriptor_m1x = 177 ModuleDescriptor.newModule("m1x") 178 .requires("java.base") 179 .exports("p1") 180 .build(); 181 182 // Set up a ModuleFinder containing all modules for this layer. 183 ModuleFinder finder = ModuleLibrary.of(descriptor_m1x); 184 185 // Resolves "m1x" 186 Configuration cf = ModuleLayer.boot() 187 .configuration() 188 .resolve(finder, ModuleFinder.of(), Set.of("m1x")); 189 190 MyDiffClassLoader.loader1 = new MyDiffClassLoader(); 191 MyDiffClassLoader.loader2 = new MyDiffClassLoader(); 192 193 // map module m1x to class loader. 194 // class c2 will be loaded in an unnamed module/loader2 195 // to achieve differing class loaders. 196 Map<String, ClassLoader> map = new HashMap<>(); 197 map.put("m1x", MyDiffClassLoader.loader1); 198 199 // Create layer that contains m1x 200 ModuleLayer layer = ModuleLayer.boot().defineModules(cf, map::get); 201 202 assertTrue(layer.findLoader("m1x") == MyDiffClassLoader.loader1); 203 assertTrue(layer.findLoader("java.base") == null); 204 205 // now use the same loader to load class p1.c1Loose 206 Class p1_c1_class = MyDiffClassLoader.loader1.loadClass("p1.c1Loose"); 207 208 // change m1x to read all unnamed modules 209 Module m1x = layer.findModule("m1x").get(); 210 jdk.internal.module.Modules.addReadsAllUnnamed(m1x); 211 212 try { 213 p1_c1_class.newInstance(); 214 } catch (IllegalAccessError e) { 215 throw new RuntimeException("Test Failed, loose module m1x should be able to access " + 216 "public type p2.c2 defined in unnamed module: " + e.getMessage()); 217 } 218 } 219 220 public static void main(String args[]) throws Throwable { 221 DiffCL_Umod test = new DiffCL_Umod(); 222 test.test_strictModuleLayer(); // access denied 223 test.test_strictModuleUnnamedReadableLayer(); // access allowed 224 test.test_looseModuleLayer(); // access allowed 225 } 226 }