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 /*
26 * @test
27 * @summary Dump time resolutiom of constant pool entries.
28 * @requires vm.cds
29 * @requires vm.compMode != "Xcomp"
30 * @library /test/lib
31 * @build ResolvedConstants
32 * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar ResolvedConstantsApp ResolvedConstantsFoo ResolvedConstantsBar
33 * @run driver ResolvedConstants
34 */
35
36 import jdk.test.lib.cds.CDSOptions;
37 import jdk.test.lib.cds.CDSTestUtils;
38 import jdk.test.lib.helpers.ClassFileInstaller;
39
40 public class ResolvedConstants {
41 static final String classList = "ResolvedConstants.classlist";
42 static final String appJar = ClassFileInstaller.getJarPath("app.jar");
43 static final String mainClass = ResolvedConstantsApp.class.getName();
44
45 public static void main(String[] args) throws Exception {
46 // dump class list
47 CDSTestUtils.dumpClassList(classList, "-cp", appJar, mainClass)
48 .assertNormalExit(output -> {
49 output.shouldContain("Hello ResolvedConstantsApp");
50 });
51
52 CDSOptions opts = (new CDSOptions())
53 .addPrefix("-XX:ExtraSharedClassListFile=" + classList,
54 "-cp", appJar,
55 "-Xlog:cds+resolve=trace");
56 CDSTestUtils.createArchiveAndCheck(opts)
57 // Class References ---
58
59 // Always resolve reference when a class references itself
60 .shouldMatch("cds,resolve.*archived klass.* ResolvedConstantsApp app => ResolvedConstantsApp app")
61
62 // Always resolve reference when a class references a super class
63 .shouldMatch("cds,resolve.*archived klass.* ResolvedConstantsApp app => java/lang/Object boot")
64 .shouldMatch("cds,resolve.*archived klass.* ResolvedConstantsBar app => ResolvedConstantsFoo app")
65
66 // Always resolve reference when a class references a super interface
67 .shouldMatch("cds,resolve.*archived klass.* ResolvedConstantsApp app => java/lang/Runnable boot")
68
69 // java/lang/System is in the root loader but ResolvedConstantsApp is loaded by the app loader.
70 // Even though System is in the vmClasses list, when ResolvedConstantsApp looks up
71 // "java/lang/System" in its ConstantPool, the app loader may not have resolved the System
72 // class yet (i.e., there's no initiaited class entry for System in the app loader's dictionary)
73 .shouldMatch("cds,resolve.*reverted klass.* ResolvedConstantsApp .*java/lang/System")
74
75 // Field References ---
76
77 // Always resolve references to fields in the current class or super class(es)
78 .shouldMatch("cds,resolve.*archived field.* ResolvedConstantsBar => ResolvedConstantsBar.b:I")
79 .shouldMatch("cds,resolve.*archived field.* ResolvedConstantsBar => ResolvedConstantsBar.a:I")
80 .shouldMatch("cds,resolve.*archived field.* ResolvedConstantsBar => ResolvedConstantsFoo.a:I")
81
82 // Do not resolve field references to child classes
83 .shouldMatch("cds,resolve.*archived field.* ResolvedConstantsFoo => ResolvedConstantsFoo.a:I")
84 .shouldMatch("cds,resolve.*reverted field.* ResolvedConstantsFoo ResolvedConstantsBar.a:I")
85 .shouldMatch("cds,resolve.*reverted field.* ResolvedConstantsFoo ResolvedConstantsBar.b:I")
86
87 // Do not resolve field references to unrelated classes
88 .shouldMatch("cds,resolve.*reverted field.* ResolvedConstantsApp ResolvedConstantsBar.a:I")
89 .shouldMatch("cds,resolve.*reverted field.* ResolvedConstantsApp ResolvedConstantsBar.b:I")
90
91 // Method References ---
92
93 // Should resolve references to own constructor
94 .shouldMatch("cds,resolve.*archived method .* ResolvedConstantsApp ResolvedConstantsApp.<init>:")
95 // Should resolve references to super constructor
96 .shouldMatch("cds,resolve.*archived method .* ResolvedConstantsApp java/lang/Object.<init>:")
97
98 // Should resolve interface methods in VM classes
99 .shouldMatch("cds,resolve.*archived interface method .* ResolvedConstantsApp java/lang/Runnable.run:")
100
101 // Should resolve references to own non-static method (private or public)
102 .shouldMatch("archived method.*: ResolvedConstantsBar ResolvedConstantsBar.doBar:")
103 .shouldMatch("archived method.*: ResolvedConstantsApp ResolvedConstantsApp.privateInstanceCall:")
104 .shouldMatch("archived method.*: ResolvedConstantsApp ResolvedConstantsApp.publicInstanceCall:")
105
106 // Should not resolve references to static method
107 .shouldNotMatch(" archived method CP entry.*: ResolvedConstantsApp ResolvedConstantsApp.staticCall:")
108
109 // Should resolve references to method in super type
110 .shouldMatch(" archived method CP entry.*: ResolvedConstantsBar ResolvedConstantsFoo.doBar:")
111
112 // App class cannot resolve references to methods in boot classes:
113 // When the app class loader tries to resolve a class X that's normally loaded by
114 // the boot loader, it's possible for the app class loader to get a different copy of
115 // X (by using MethodHandles.Lookup.defineClass(), etc). Therefore, let's be on
116 // the side of safety and revert all such references.
117 //
118 // This will be addressed in JDK-8315737.
119 .shouldMatch("reverted method.*: ResolvedConstantsApp java/io/PrintStream.println:")
120 .shouldMatch("reverted method.*: ResolvedConstantsBar java/lang/Class.getName:")
121
122 // Should not resolve methods in unrelated classes.
123 .shouldMatch("reverted method.*: ResolvedConstantsApp ResolvedConstantsBar.doit:")
124
125 // End ---
126 ;
127 }
128 }
129
130 class ResolvedConstantsApp implements Runnable {
131 public static void main(String args[]) {
132 System.out.println("Hello ResolvedConstantsApp");
133 ResolvedConstantsApp app = new ResolvedConstantsApp();
134 ResolvedConstantsApp.staticCall();
135 app.privateInstanceCall();
136 app.publicInstanceCall();
137 Object a = app;
138 ((Runnable)a).run();
139
140 ResolvedConstantsFoo foo = new ResolvedConstantsFoo();
141 ResolvedConstantsBar bar = new ResolvedConstantsBar();
142 bar.a ++;
143 bar.b ++;
144 bar.doit();
145 }
146 private static void staticCall() {}
147 private void privateInstanceCall() {}
148 public void publicInstanceCall() {}
149
150 public void run() {}
151 }
152
153 class ResolvedConstantsFoo {
154 int a = 1;
155 void doit() {
156 }
157
158 void doBar(ResolvedConstantsBar bar) {
159 bar.a ++;
160 bar.b ++;
161 }
162 }
163
164 class ResolvedConstantsBar extends ResolvedConstantsFoo {
165 int b = 2;
166 void doit() {
167 System.out.println("Hello ResolvedConstantsBar and " + ResolvedConstantsFoo.class.getName());
168 System.out.println("a = " + a);
169 System.out.println("a = " + ((ResolvedConstantsFoo)this).a);
170 System.out.println("b = " + b);
|
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 /*
26 * @test
27 * @summary Dump time resolution of constant pool entries.
28 * @requires vm.cds
29 * @requires vm.cds.supports.aot.class.linking
30 * @requires vm.compMode != "Xcomp"
31 * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds/test-classes/
32 * @build OldProvider OldClass OldConsumer
33 * @build ResolvedConstants
34 * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar
35 * ResolvedConstantsApp ResolvedConstantsFoo ResolvedConstantsBar
36 * MyInterface InterfaceWithClinit NormalClass
37 * OldProvider OldClass OldConsumer SubOfOldClass
38 * @run driver ResolvedConstants
39 */
40
41 import java.util.function.Consumer;
42 import jdk.test.lib.cds.CDSOptions;
43 import jdk.test.lib.cds.CDSTestUtils;
44 import jdk.test.lib.helpers.ClassFileInstaller;
45 import jdk.test.lib.process.OutputAnalyzer;
46
47 public class ResolvedConstants {
48 static final String classList = "ResolvedConstants.classlist";
49 static final String appJar = ClassFileInstaller.getJarPath("app.jar");
50 static final String mainClass = ResolvedConstantsApp.class.getName();
51
52 static boolean aotClassLinking;
53 public static void main(String[] args) throws Exception {
54 test(false);
55 test(true);
56 }
57
58 static void test(boolean testMode) throws Exception {
59 aotClassLinking = testMode;
60 CDSTestUtils.dumpClassList(classList, "-cp", appJar, mainClass)
61 .assertNormalExit(output -> {
62 output.shouldContain("Hello ResolvedConstantsApp");
63 });
64
65 CDSOptions opts = (new CDSOptions())
66 .addPrefix("-XX:ExtraSharedClassListFile=" + classList,
67 "-cp", appJar,
68 "-Xlog:cds+resolve=trace",
69 "-Xlog:cds+class=debug");
70 if (aotClassLinking) {
71 opts.addPrefix("-XX:+AOTClassLinking");
72 } else {
73 opts.addPrefix("-XX:-AOTClassLinking");
74 }
75
76 OutputAnalyzer out = CDSTestUtils.createArchiveAndCheck(opts);
77 // Class References ---
78
79 // Always resolve reference when a class references itself
80 out.shouldMatch(ALWAYS("klass.* ResolvedConstantsApp app => ResolvedConstantsApp app"))
81
82 // Always resolve reference when a class references a super class
83 .shouldMatch(ALWAYS("klass.* ResolvedConstantsApp app => java/lang/Object boot"))
84 .shouldMatch(ALWAYS("klass.* ResolvedConstantsBar app => ResolvedConstantsFoo app"))
85
86 // Always resolve reference when a class references a super interface
87 .shouldMatch(ALWAYS("klass.* ResolvedConstantsApp app => java/lang/Runnable boot"))
88
89 /** premain allows static method pre-resolution
90
91 // Without -XX:+AOTClassLinking:
92 // java/lang/System is in the boot loader but ResolvedConstantsApp is loaded by the app loader.
93 // Even though System is in the vmClasses list, when ResolvedConstantsApp looks up
94 // "java/lang/System" in its ConstantPool, the app loader may not have resolved the System
95 // class yet (i.e., there's no initiaited class entry for System in the app loader's dictionary)
96 .shouldMatch(AOTLINK_ONLY("klass.* ResolvedConstantsApp .*java/lang/System"))
97 **/
98 // Field References ---
99
100 // Always resolve references to fields in the current class or super class(es)
101 .shouldMatch(ALWAYS("field.* ResolvedConstantsBar => ResolvedConstantsBar.b:I"))
102 .shouldMatch(ALWAYS("field.* ResolvedConstantsBar => ResolvedConstantsBar.a:I"))
103 .shouldMatch(ALWAYS("field.* ResolvedConstantsBar => ResolvedConstantsFoo.a:I"))
104 .shouldMatch(ALWAYS("field.* ResolvedConstantsFoo => ResolvedConstantsFoo.a:I"))
105
106 // Resolve field references to child classes ONLY when using -XX:+AOTClassLinking
107 .shouldMatch(AOTLINK_ONLY("field.* ResolvedConstantsFoo => ResolvedConstantsBar.a:I"))
108 .shouldMatch(AOTLINK_ONLY("field.* ResolvedConstantsFoo => ResolvedConstantsBar.b:I"))
109
110 // Resolve field references to unrelated classes ONLY when using -XX:+AOTClassLinking
111 .shouldMatch(AOTLINK_ONLY("field.* ResolvedConstantsApp => ResolvedConstantsBar.a:I"))
112 .shouldMatch(AOTLINK_ONLY("field.* ResolvedConstantsApp => ResolvedConstantsBar.b:I"))
113
114 // Method References ---
115
116 // Should resolve references to own constructor
117 .shouldMatch(ALWAYS("method.* ResolvedConstantsApp ResolvedConstantsApp.<init>:"))
118 // Should resolve references to super constructor
119 .shouldMatch(ALWAYS("method.* ResolvedConstantsApp java/lang/Object.<init>:"))
120
121 // Should resolve interface methods in VM classes
122 .shouldMatch(ALWAYS("interface method .* ResolvedConstantsApp java/lang/Runnable.run:"))
123
124 // Should resolve references to own non-static method (private or public)
125 .shouldMatch(ALWAYS("method.*: ResolvedConstantsBar ResolvedConstantsBar.doBar:"))
126 .shouldMatch(ALWAYS("method.*: ResolvedConstantsApp ResolvedConstantsApp.privateInstanceCall:"))
127 .shouldMatch(ALWAYS("method.*: ResolvedConstantsApp ResolvedConstantsApp.publicInstanceCall:"))
128
129 /** premain allows static method pre-resolution
130
131 // Should not resolve references to static method
132 .shouldNotMatch(ALWAYS("method.*: ResolvedConstantsApp ResolvedConstantsApp.staticCall:"))
133 **/
134
135 // Should resolve references to method in super type
136 .shouldMatch(ALWAYS("method.*: ResolvedConstantsBar ResolvedConstantsFoo.doBar:"))
137
138 // Without -XX:+AOTClassLinking App class cannot resolve references to methods in boot classes:
139 // When the app class loader tries to resolve a class X that's normally loaded by
140 // the boot loader, it's possible for the app class loader to get a different copy of
141 // X (by using MethodHandles.Lookup.defineClass(), etc). Therefore, let's be on
142 // the side of safety and revert all such references.
143 .shouldMatch(AOTLINK_ONLY("method.*: ResolvedConstantsApp java/io/PrintStream.println:"))
144 .shouldMatch(AOTLINK_ONLY("method.*: ResolvedConstantsBar java/lang/Class.getName:"))
145
146 // Resole resolve methods in unrelated classes ONLY when using -XX:+AOTClassLinking
147 .shouldMatch(AOTLINK_ONLY("method.*: ResolvedConstantsApp ResolvedConstantsBar.doit:"))
148
149 // End ---
150 ;
151
152
153 // Indy References ---
154 if (aotClassLinking) {
155 /** premain allows Old classes to be linked
156 out.shouldContain("Cannot aot-resolve Lambda proxy because OldConsumer is excluded")
157 .shouldContain("Cannot aot-resolve Lambda proxy because OldProvider is excluded")
158 .shouldContain("Cannot aot-resolve Lambda proxy because OldClass is excluded")
159 .shouldContain("Cannot aot-resolve Lambda proxy of interface type InterfaceWithClinit (has <cilint>)")
160 .shouldMatch("klasses.* app *NormalClass[$][$]Lambda/.* hidden aot-linked inited")
161 .shouldNotMatch("klasses.* app *SubOfOldClass[$][$]Lambda/");
162 **/
163 }
164 }
165
166 static String ALWAYS(String s) {
167 return "cds,resolve.*archived " + s;
168 }
169
170 static String AOTLINK_ONLY(String s) {
171 if (aotClassLinking) {
172 return ALWAYS(s);
173 } else {
174 return "cds,resolve.*reverted " + s;
175 }
176 }
177 }
178
179 class ResolvedConstantsApp implements Runnable {
180 public static void main(String args[]) {
181 System.out.println("Hello ResolvedConstantsApp");
182 ResolvedConstantsApp app = new ResolvedConstantsApp();
183 ResolvedConstantsApp.staticCall();
184 app.privateInstanceCall();
185 app.publicInstanceCall();
186 Object a = app;
187 ((Runnable)a).run();
188
189 ResolvedConstantsFoo foo = new ResolvedConstantsFoo();
190 ResolvedConstantsBar bar = new ResolvedConstantsBar();
191 bar.a ++;
192 bar.b ++;
193 bar.doit();
194
195 testLambda();
196 }
197 private static void staticCall() {}
198 private void privateInstanceCall() {}
199 public void publicInstanceCall() {}
200
201 public void run() {}
202
203 static void testLambda() {
204 // The functional type used in the Lambda is an excluded class
205 OldProvider op = () -> {
206 return null;
207 };
208
209 // A captured value is an instance of an excluded Class
210 OldClass c = new OldClass();
211 Runnable r = () -> {
212 System.out.println("Test 1 " + c);
213 };
214 r.run();
215
216 // The functional interface accepts an argument that's an excluded class
217 MyInterface i = (o) -> {
218 System.out.println("Test 2 " + o);
219 };
220 i.dispatch(c);
221
222 // Method reference to old class
223 OldConsumer oldConsumer = new OldConsumer();
224 Consumer<String> wrapper = oldConsumer::consumeString;
225 wrapper.accept("Hello");
226
227 // Lambda of interfaces that have <clinit> are not archived.
228 InterfaceWithClinit i2 = () -> {
229 System.out.println("Test 3");
230 };
231 i2.dispatch();
232
233 // These two classes have almost identical source code, but
234 // only NormalClass should have its lambdas pre-resolved.
235 // SubOfOldClass is "old" -- it should be excluded from the AOT cache,
236 // so none of its lambda proxies should be cached
237 NormalClass.testLambda(); // Lambda proxy should be cached
238 SubOfOldClass.testLambda(); // Lambda proxy shouldn't be cached
239 }
240 }
241
242 class NormalClass {
243 static void testLambda() {
244 Runnable r = () -> {
245 System.out.println("NormalClass testLambda");
246 };
247 r.run();
248 }
249 }
250
251 class SubOfOldClass extends OldClass {
252 static void testLambda() {
253 Runnable r = () -> {
254 System.out.println("SubOfOldClass testLambda");
255 };
256 r.run();
257 }
258 }
259
260 interface MyInterface {
261 void dispatch(OldClass c);
262 }
263
264 interface InterfaceWithClinit {
265 static final long X = System.currentTimeMillis();
266 void dispatch();
267 }
268
269 class ResolvedConstantsFoo {
270 int a = 1;
271 void doit() {
272 }
273
274 void doBar(ResolvedConstantsBar bar) {
275 bar.a ++;
276 bar.b ++;
277 }
278 }
279
280 class ResolvedConstantsBar extends ResolvedConstantsFoo {
281 int b = 2;
282 void doit() {
283 System.out.println("Hello ResolvedConstantsBar and " + ResolvedConstantsFoo.class.getName());
284 System.out.println("a = " + a);
285 System.out.println("a = " + ((ResolvedConstantsFoo)this).a);
286 System.out.println("b = " + b);
|