1 /*
  2  * Copyright (c) 2021, 2023, 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  * @bug 8276184
 28  * @summary If the caller class is redefined during dump time, the caller class
 29  *          and its lambda proxy class should not be archived.
 30  * @requires vm.cds
 31  * @requires vm.jvmti
 32  * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
 33  *          /test/hotspot/jtreg/runtime/cds/appcds/test-classes
 34  *          /test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes
 35  * @build jdk.test.whitebox.WhiteBox OldProvider
 36  * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
 37  * @run driver RedefineClassHelper
 38  * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. RedefineCallerClassTest
 39  */
 40 
 41 import jdk.test.lib.helpers.ClassFileInstaller;
 42 
 43 public class RedefineCallerClassTest extends DynamicArchiveTestBase {
 44     static String mainClass = RedefineCallerClass.class.getName();
 45 
 46     static String providerClass = OldProvider.class.getName();
 47 
 48     static String sharedClasses[] = {
 49         mainClass,
 50         "SimpleLambda", // caller class will be redefined in RedefineCallerClass
 51         providerClass,  // inteface with class file major version < 50
 52         "jdk/test/lib/compiler/InMemoryJavaCompiler",
 53         "jdk/test/lib/compiler/InMemoryJavaCompiler$FileManagerWrapper",
 54         "jdk/test/lib/compiler/InMemoryJavaCompiler$FileManagerWrapper$1",
 55         "jdk/test/lib/compiler/InMemoryJavaCompiler$MemoryJavaFileObject"
 56     };
 57 
 58     public static void main(String[] args) throws Exception {
 59         runTest(RedefineCallerClassTest::test);
 60     }
 61 
 62     static void test() throws Exception {
 63         String topArchiveName = getNewArchiveName();
 64         String appJar = ClassFileInstaller.writeJar("redefine_caller_class.jar", sharedClasses);
 65 
 66         String[] mainArgs = {
 67             "redefineCaller", // redefine caller class only
 68             "useOldInf",      // use old interface only
 69             "both"            // both of the above
 70         };
 71 
 72         for (String mainArg : mainArgs) {
 73             String[] options = {
 74                 "-Xlog:class+load,cds",
 75                 "-XX:+UnlockDiagnosticVMOptions",
 76                 "-XX:+AllowArchivingWithJavaAgent",
 77                 "-javaagent:redefineagent.jar",
 78                 "-cp", appJar, mainClass, mainArg
 79             };
 80 
 81             dump(topArchiveName, options)
 82                 .assertNormalExit(output -> {
 83                     output.shouldHaveExitValue(0);
 84                     if (mainArg.equals("both") || mainArg.equals("useOldInf")) {
 85                         output.shouldContain("Skipping OldProvider: Old class has been linked")
 86                               .shouldMatch("Skipping.SimpleLambda[$][$]Lambda.*0x.*:.*Old.class.has.been.linked");
 87                     }
 88                     if (mainArg.equals("both") || mainArg.equals("redefineCaller")) {
 89                         output.shouldContain("Skipping SimpleLambda: Has been redefined");
 90                     }
 91                 });
 92 
 93             run(topArchiveName, options)
 94                 .assertNormalExit(output -> {
 95                     output.shouldHaveExitValue(0)
 96                           .shouldContain("RedefineCallerClass source: shared objects file (top)")
 97                           .shouldMatch(".class.load. SimpleLambda[$][$]Lambda.*/0x.*source:.*SimpleLambda");
 98                     if (mainArg.equals("both") || mainArg.equals("useOldInf")) {
 99                         output.shouldMatch(".class.load. OldProvider.source:.*redefine_caller_class.jar");
100                     }
101                     if (mainArg.equals("both") || mainArg.equals("redefineCaller")) {
102                         output.shouldMatch(".class.load. SimpleLambda.source:.*redefine_caller_class.jar");
103                     }
104                 });
105         }
106     }
107 }