8342303: Segfault in update_inherited_vtable: AppCDS, old bytecode, and redefineClasses

Reviewed-by: dholmes, coleenp, iklam
This commit is contained in:
Calvin Cheung 2024-11-07 18:27:27 +00:00
parent 4f5a241ec1
commit ccda8159f6
14 changed files with 505 additions and 5 deletions

View File

@ -2639,10 +2639,15 @@ void InstanceKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handl
// have been redefined.
bool trace_name_printed = false;
adjust_default_methods(&trace_name_printed);
vtable().initialize_vtable();
itable().initialize_itable();
if (verified_at_dump_time()) {
// Initialize vtable and itable for classes which can be verified at dump time.
// Unlinked classes such as old classes with major version < 50 cannot be verified
// at dump time.
vtable().initialize_vtable();
itable().initialize_itable();
}
}
#endif
#endif // INCLUDE_JVMTI
// restore constant pool resolved references
constants()->restore_unshareable_info(CHECK);

View File

@ -444,6 +444,7 @@ hotspot_appcds_dynamic = \
-runtime/cds/appcds/jcmd/JCmdTestStaticDump.java \
-runtime/cds/appcds/jcmd/JCmdTestDynamicDump.java \
-runtime/cds/appcds/jcmd/JCmdTestFileSafety.java \
-runtime/cds/appcds/jvmti/redefineClasses/OldClassAndRedefineClass.java \
-runtime/cds/appcds/lambdaForm/DefaultClassListLFInvokers.java \
-runtime/cds/appcds/methodHandles \
-runtime/cds/appcds/sharedStrings \

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
public class BootChild extends BootSuper {
// Does not override BootSuper::doit()
}

View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
public class BootSuper {
public String doit() {
return "Hello";
}
}

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
public class NewChild extends OldSuper {
// Does not override BootSuper::doit()
}

View File

@ -0,0 +1,79 @@
/*
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
/*
* @test
* @bug 8342303
* @summary Test loading of shared old class when another class has been redefined.
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds /test/hotspot/jtreg/runtime/cds/appcds/test-classes /test/hotspot/jtreg/runtime/cds/appcds/jvmti
* @requires vm.cds.write.archived.java.heap
* @requires vm.jvmti
* @build jdk.test.whitebox.WhiteBox
* OldClassAndRedefineClassApp
* @compile ../../test-classes/OldSuper.jasm
* ../../test-classes/ChildOldSuper.java
* ../../test-classes/Hello.java
* @run driver RedefineClassHelper
* @run driver OldClassAndRedefineClass
*/
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.helpers.ClassFileInstaller;
public class OldClassAndRedefineClass {
public static String appClasses[] = {
"OldClassAndRedefineClassApp",
"OldSuper",
"ChildOldSuper",
"Hello",
};
public static String sharedClasses[] = TestCommon.concat(appClasses);
public static void main(String[] args) throws Throwable {
runTest();
}
public static void runTest() throws Throwable {
String appJar =
ClassFileInstaller.writeJar("OldClassAndRedefineClassApp.jar", appClasses);
String agentCmdArg = "-javaagent:redefineagent.jar";
OutputAnalyzer out = TestCommon.testDump(appJar, sharedClasses, "-Xlog:cds,cds+class=debug");
out.shouldMatch("klasses.*OldSuper.[*][*].unlinked")
.shouldMatch("klasses.*ChildOldSuper.[*][*].unlinked");
out = TestCommon.exec(
appJar,
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+AllowArchivingWithJavaAgent",
"-XX:+WhiteBoxAPI",
"-Xlog:cds,class+load",
agentCmdArg,
"OldClassAndRedefineClassApp");
out.shouldContain("[class,load] OldSuper source: shared objects file")
.shouldContain("[class,load] ChildOldSuper source: shared objects file")
.shouldContain("[class,load] Hello source: __VM_RedefineClasses__");
}
}

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
public class OldClassAndRedefineClassApp {
public static void main(String args[]) throws Throwable {
ClassLoader appClassLoader = ClassLoader.getSystemClassLoader();
System.out.println("Main: loading OldSuper");
// Load an old class (version 49), but not linking it.
Class.forName("OldSuper", false, appClassLoader);
// Redefine a class unrelated to the above old class.
System.out.println("INFO: instrumentation = " + RedefineClassHelper.instrumentation);
Class<?> c = Class.forName("Hello", false, appClassLoader);
byte[] bytes = c.getClassLoader().getResourceAsStream(c.getName().replace('.', '/') + ".class").readAllBytes();
RedefineClassHelper.redefineClass(c, bytes);
System.out.println("Main: loading ChildOldSuper");
// Load and link a subclass of the above old class.
// This will in turn link the old class and initializes its vtable, etc.
Class.forName("ChildOldSuper");
}
}

View File

@ -0,0 +1,66 @@
/*
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
import java.io.File;
public class RedefineBootClassApp {
public static void main(String args[]) throws Throwable {
File bootJar = new File(args[0]);
Class<?> superCls = Class.forName("BootSuper", false, null);
System.out.println("BootSuper>> loader = " + superCls.getClassLoader());
{
BootSuper obj = (BootSuper)superCls.newInstance();
System.out.println("(before transform) BootSuper>> doit() = " + obj.doit());
}
// Redefine the class
byte[] bytes = Util.getClassFileFromJar(bootJar, "BootSuper");
Util.replace(bytes, "Hello", "HELLO");
RedefineClassHelper.redefineClass(superCls, bytes);
{
BootSuper obj = (BootSuper)superCls.newInstance();
String s = obj.doit();
System.out.println("(after transform) BootSuper>> doit() = " + s);
if (!s.equals("HELLO")) {
throw new RuntimeException("BootSuper doit() should be HELLO but got " + s);
}
}
Class<?> childCls = Class.forName("BootChild", false, null);
System.out.println("BootChild>> loader = " + childCls.getClassLoader());
{
BootSuper obj = (BootSuper)childCls.newInstance();
String s = obj.doit();
System.out.println("(after transform) BootChild>> doit() = " + s);
if (!s.equals("HELLO")) {
throw new RuntimeException("BootChild doit() should be HELLO but got " + s);
}
}
}
}

View File

@ -0,0 +1,79 @@
/*
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
/*
* @test
* @bug 8342303
* @summary Redefine a shared super class loaded by the boot loader. The vtable of its archived child class must be updated
* @library /test/lib
* /test/hotspot/jtreg/runtime/cds/appcds
* /test/hotspot/jtreg/runtime/cds/appcds/test-classes
* /test/hotspot/jtreg/runtime/cds/appcds/jvmti
* @requires vm.jvmti
* @build RedefineBootClassTest
* RedefineBootClassApp
* BootSuper BootChild
* @run driver RedefineClassHelper
* @run driver RedefineBootClassTest
*/
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.helpers.ClassFileInstaller;
public class RedefineBootClassTest {
public static String bootClasses[] = {
"BootSuper",
"BootChild",
};
public static String appClasses[] = {
"RedefineBootClassApp",
"Util",
};
public static String sharedClasses[] = TestCommon.concat(bootClasses, appClasses);
public static void main(String[] args) throws Throwable {
runTest();
}
public static void runTest() throws Throwable {
String bootJar =
ClassFileInstaller.writeJar("RedefineClassBoot.jar", bootClasses);
String appJar =
ClassFileInstaller.writeJar("RedefineClassApp.jar", appClasses);
String bootCP = "-Xbootclasspath/a:" + bootJar;
String agentCmdArg = "-javaagent:redefineagent.jar";
TestCommon.testDump(appJar, sharedClasses, bootCP, "-Xlog:cds,cds+class=debug");
OutputAnalyzer out = TestCommon.execAuto("-cp", appJar,
bootCP,
"-XX:+UnlockDiagnosticVMOptions",
"-Xlog:cds=info,class+load",
agentCmdArg,
"RedefineBootClassApp", bootJar);
out.reportDiagnosticSummary();
TestCommon.checkExec(out);
}
}

View File

@ -0,0 +1,67 @@
/*
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
import java.io.File;
public class RedefineOldSuperApp {
public static void main(String args[]) throws Throwable {
File bootJar = new File(args[0]);
ClassLoader appClassLoader = ClassLoader.getSystemClassLoader();
Class<?> superCls = Class.forName("OldSuper", false, appClassLoader);
System.out.println("OldSuper>> loader = " + superCls.getClassLoader());
{
OldSuper obj = (OldSuper)superCls.newInstance();
System.out.println("(before transform) OldSuper>> doit() = " + obj.doit());
}
// Redefine the class
byte[] bytes = Util.getClassFileFromJar(bootJar, "OldSuper");
Util.replace(bytes, "Hello", "HELLO");
RedefineClassHelper.redefineClass(superCls, bytes);
{
OldSuper obj = (OldSuper)superCls.newInstance();
String s = obj.doit();
System.out.println("(after transform) OldSuper>> doit() = " + s);
if (!s.equals("HELLO")) {
throw new RuntimeException("OldSuper doit() should be HELLO but got " + s);
}
}
Class<?> childCls = Class.forName("NewChild", false, appClassLoader);
System.out.println("NewChild>> loader = " + childCls.getClassLoader());
{
OldSuper obj = (OldSuper)childCls.newInstance();
String s = obj.doit();
System.out.println("(after transform) NewChild>> doit() = " + s);
if (!s.equals("HELLO")) {
throw new RuntimeException("NewChild doit() should be HELLO but got " + s);
}
}
}
}

View File

@ -0,0 +1,74 @@
/*
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
/*
* @test
* @bug 8342303
* @summary Redefine a shared old super class loaded by the app loader. The vtable of its archived child class must be updated
* @library /test/lib
* /test/hotspot/jtreg/runtime/cds/appcds
* /test/hotspot/jtreg/runtime/cds/appcds/test-classes
* /test/hotspot/jtreg/runtime/cds/appcds/jvmti
* @requires vm.jvmti
* @compile ../../test-classes/OldSuper.jasm
* @build RedefineOldSuperTest
* RedefineOldSuperApp
* NewChild
* @run driver RedefineClassHelper
* @run driver RedefineOldSuperTest
*/
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.helpers.ClassFileInstaller;
public class RedefineOldSuperTest {
public static String appClasses[] = {
"OldSuper",
"NewChild",
"RedefineOldSuperApp",
"Util",
};
public static String sharedClasses[] = TestCommon.concat(appClasses);
public static void main(String[] args) throws Throwable {
runTest();
}
public static void runTest() throws Throwable {
String appJar =
ClassFileInstaller.writeJar("RedefineClassApp.jar", appClasses);
String agentCmdArg = "-javaagent:redefineagent.jar";
TestCommon.testDump(appJar, sharedClasses, "-Xlog:cds,cds+class=debug");
OutputAnalyzer out = TestCommon.execAuto("-cp", appJar,
"-XX:+UnlockDiagnosticVMOptions",
"-Xlog:cds=info,class+load",
agentCmdArg,
"RedefineOldSuperApp", appJar);
out.reportDiagnosticSummary();
TestCommon.checkExec(out);
}
}

View File

@ -30,7 +30,7 @@
* @requires vm.jvmti
* @library /test/lib /test/hotspot/jtreg/serviceability/jvmti/RedefineClasses /test/hotspot/jtreg/runtime/cds/appcds
* @run driver RedefineClassHelper
* @build jdk.test.whitebox.WhiteBox RedefineBasic
* @build jdk.test.whitebox.WhiteBox jdk.test.lib.compiler.InMemoryJavaCompiler RedefineBasic
* @run driver RedefineBasicTest
*/

View File

@ -30,7 +30,7 @@
* @requires vm.jvmti
* @library /test/lib /test/hotspot/jtreg/serviceability/jvmti/RedefineClasses /test/hotspot/jtreg/runtime/cds/appcds
* @run driver RedefineClassHelper
* @build jdk.test.whitebox.WhiteBox
* @build jdk.test.whitebox.WhiteBox jdk.test.lib.compiler.InMemoryJavaCompiler
* @compile RedefineRunningMethods_SharedHelper.java
* @run driver RedefineRunningMethods_Shared
*/

View File

@ -30,6 +30,7 @@
* @modules java.compiler
* java.instrument
* @requires vm.jvmti
* @build jdk.test.lib.compiler.InMemoryJavaCompiler
* @run main RedefineClassHelper
* @run main/othervm -Xmx256m -XX:MaxMetaspaceSize=64m -javaagent:redefineagent.jar -Xlog:all=trace:file=all.log RedefineClasses
*/