|
1 /* |
|
2 Copyright (c) 2017, 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 * @bug 8174954 |
|
27 * @summary Test that invokedynamic instructions, that initially throw IAE exceptions |
|
28 * because of a missing module read edge, behave correctly when executed |
|
29 * after the module read edge is added. |
|
30 * @compile ModuleLibrary.java |
|
31 * p2/c2.java |
|
32 * p5/c5.java |
|
33 * p7/c7.java |
|
34 * @run main/othervm MethodAccessReadTwice |
|
35 */ |
|
36 |
|
37 import java.lang.module.Configuration; |
|
38 import java.lang.module.ModuleDescriptor; |
|
39 import java.lang.module.ModuleFinder; |
|
40 import java.lang.ModuleLayer; |
|
41 import java.lang.Module; |
|
42 import java.util.HashMap; |
|
43 import java.util.Map; |
|
44 import java.util.Set; |
|
45 |
|
46 // defines first_mod --> packages p5 |
|
47 // defines second_mod --> package p2, p2 is exported to first_mod |
|
48 // defines third_mod --> packages p7 |
|
49 |
|
50 public class MethodAccessReadTwice { |
|
51 |
|
52 // Create a Layer over the boot layer. |
|
53 // Define modules within this layer to test access between |
|
54 // publicly defined classes within packages of those modules. |
|
55 public void createLayerOnBoot() throws Throwable { |
|
56 |
|
57 // Define module: first_mod |
|
58 // Can read: java.base |
|
59 // Packages: p5 |
|
60 // Packages exported: p5 is exported unqualifiedly |
|
61 ModuleDescriptor descriptor_first_mod = |
|
62 ModuleDescriptor.newModule("first_mod") |
|
63 .requires("java.base") |
|
64 .exports("p5") |
|
65 .build(); |
|
66 |
|
67 // Define module: second_mod |
|
68 // Can read: java.base |
|
69 // Packages: p2 |
|
70 // Packages exported: p2 is exported to first_mod |
|
71 ModuleDescriptor descriptor_second_mod = |
|
72 ModuleDescriptor.newModule("second_mod") |
|
73 .requires("java.base") |
|
74 .exports("p2") |
|
75 .build(); |
|
76 |
|
77 // Define module: third_mod |
|
78 // Can read: java.base |
|
79 // Packages: p7 |
|
80 // Packages exported: p7 is exported unqualifiedly |
|
81 ModuleDescriptor descriptor_third_mod = |
|
82 ModuleDescriptor.newModule("third_mod") |
|
83 .requires("java.base") |
|
84 .exports("p7") |
|
85 .build(); |
|
86 |
|
87 // Set up a ModuleFinder containing all modules for this layer |
|
88 ModuleFinder finder = ModuleLibrary.of(descriptor_first_mod, |
|
89 descriptor_second_mod, |
|
90 descriptor_third_mod); |
|
91 |
|
92 // Resolves "first_mod", "second_mod", and "third_mod" |
|
93 Configuration cf = ModuleLayer.boot() |
|
94 .configuration() |
|
95 .resolve(finder, ModuleFinder.of(), |
|
96 Set.of("first_mod", "second_mod", "third_mod")); |
|
97 |
|
98 // Map each module to this class loader |
|
99 Map<String, ClassLoader> map = new HashMap<>(); |
|
100 ClassLoader loader = MethodAccessReadTwice.class.getClassLoader(); |
|
101 map.put("first_mod", loader); |
|
102 map.put("second_mod", loader); |
|
103 map.put("third_mod", loader); |
|
104 |
|
105 // Create Layer that contains first_mod, second_mod, and third_mod |
|
106 ModuleLayer layer = ModuleLayer.boot().defineModules(cf, map::get); |
|
107 |
|
108 Class p2_c2_class = loader.loadClass("p2.c2"); |
|
109 Class p5_c5_class = loader.loadClass("p5.c5"); |
|
110 Class p7_c7_class = loader.loadClass("p7.c7"); |
|
111 |
|
112 Module first_mod = p5_c5_class.getModule(); |
|
113 Module second_mod = p2_c2_class.getModule(); |
|
114 Module third_mod = p7_c7_class.getModule(); |
|
115 |
|
116 p5.c5 c5_obj = new p5.c5(); |
|
117 p2.c2 c2_obj = new p2.c2(); |
|
118 p7.c7 c7_obj = new p7.c7(); |
|
119 |
|
120 // Test that if an invokedynamic instruction gets an IAE exception because |
|
121 // of a module read issue, and then the read issue is fixed, that |
|
122 // re-executing the same invokedynamic instruction will get the same IAE. |
|
123 |
|
124 // First access check for p5.c5 --> call to method5 --> tries to access p2.c2 |
|
125 try { |
|
126 // Should throw IAE because p5.c5's module cannot read p2.c2's module. |
|
127 c5_obj.method5(c2_obj); |
|
128 throw new RuntimeException("Test Failed, module first_mod should not have access to p2.c2"); |
|
129 } catch (IllegalAccessError e) { |
|
130 String message = e.getMessage(); |
|
131 if (!(message.contains("cannot access") && |
|
132 message.contains("because module first_mod does not read module second_mod"))) { |
|
133 throw new RuntimeException("Wrong message: " + message); |
|
134 } else { |
|
135 System.out.println("Test Succeeded at attempt #1"); |
|
136 } |
|
137 } |
|
138 |
|
139 // Add a read edge from p5/c5's module (first_mod) to p2.c2's module (second_mod) |
|
140 c5_obj.methodAddReadEdge(p2_c2_class.getModule()); |
|
141 // Second access check for p5.c5, should have same result as first |
|
142 try { |
|
143 c5_obj.method5(c2_obj); // should result in IAE |
|
144 throw new RuntimeException("Test Failed, access should have been cached above"); |
|
145 } catch (IllegalAccessError e) { |
|
146 String message = e.getMessage(); |
|
147 if (!(message.contains("cannot access") && |
|
148 message.contains("because module first_mod does not read module second_mod"))) { |
|
149 throw new RuntimeException("Wrong message: " + message); |
|
150 } else { |
|
151 System.out.println("Test Succeeded at attempt #2"); |
|
152 } |
|
153 } |
|
154 |
|
155 |
|
156 // Test that if one invokedynamic instruction gets an IAE exception |
|
157 // because of a module read issue, and then the read issue is fixed, that |
|
158 // a subsequent invokedynamic instruction, that tries the same access, |
|
159 // succeeds. |
|
160 c7_obj.method7(c2_obj, second_mod); // Should not result in IAE |
|
161 } |
|
162 |
|
163 public static void main(String args[]) throws Throwable { |
|
164 MethodAccessReadTwice test = new MethodAccessReadTwice(); |
|
165 test.createLayerOnBoot(); |
|
166 } |
|
167 } |