1 /* 2 * Copyright (c) 2024, 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 /* 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); 171 172 doBar(this); 173 174 ((ResolvedConstantsFoo)this).doBar(this); 175 } 176 }