8259275: JRuby crashes while resolving invokedynamic instruction

Reviewed-by: iklam, minqi, lfoltan
This commit is contained in:
Calvin Cheung 2021-01-13 05:51:52 +00:00
parent 1cf2378bda
commit 15dd8f3aa4
8 changed files with 196 additions and 38 deletions

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2021, 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
@ -460,19 +460,34 @@ bool ClassListParser::is_matching_cp_entry(constantPoolHandle &pool, int cp_inde
}
return true;
}
void ClassListParser::resolve_indy(Symbol* class_name_symbol, TRAPS) {
ClassListParser::resolve_indy_impl(class_name_symbol, THREAD);
if (HAS_PENDING_EXCEPTION) {
ResourceMark rm(THREAD);
char* ex_msg = (char*)"";
oop message = java_lang_Throwable::message(PENDING_EXCEPTION);
if (message != NULL) {
ex_msg = java_lang_String::as_utf8_string(message);
}
log_warning(cds)("resolve_indy for class %s has encountered exception: %s %s",
class_name_symbol->as_C_string(),
PENDING_EXCEPTION->klass()->external_name(),
ex_msg);
CLEAR_PENDING_EXCEPTION;
}
}
void ClassListParser::resolve_indy_impl(Symbol* class_name_symbol, TRAPS) {
Handle class_loader(THREAD, SystemDictionary::java_system_loader());
Handle protection_domain;
Klass* klass = SystemDictionary::resolve_or_fail(class_name_symbol, class_loader, protection_domain, true, THREAD); // FIXME should really be just a lookup
Klass* klass = SystemDictionary::resolve_or_fail(class_name_symbol, class_loader, protection_domain, true, CHECK); // FIXME should really be just a lookup
if (klass != NULL && klass->is_instance_klass()) {
InstanceKlass* ik = InstanceKlass::cast(klass);
if (SystemDictionaryShared::has_class_failed_verification(ik)) {
// don't attempt to resolve indy on classes that has previously failed verification
return;
}
MetaspaceShared::try_link_class(ik, THREAD);
assert(!HAS_PENDING_EXCEPTION, "unexpected exception");
MetaspaceShared::try_link_class(ik, CHECK);
ConstantPool* cp = ik->constants();
ConstantPoolCache* cpcache = cp->cache();
@ -484,36 +499,23 @@ void ClassListParser::resolve_indy(Symbol* class_name_symbol, TRAPS) {
constantPoolHandle pool(THREAD, cp);
if (pool->tag_at(pool_index).is_invoke_dynamic()) {
BootstrapInfo bootstrap_specifier(pool, pool_index, indy_index);
Handle bsm = bootstrap_specifier.resolve_bsm(THREAD);
Handle bsm = bootstrap_specifier.resolve_bsm(CHECK);
if (!SystemDictionaryShared::is_supported_invokedynamic(&bootstrap_specifier)) {
log_debug(cds, lambda)("is_supported_invokedynamic check failed for cp_index %d", pool_index);
continue;
}
if (is_matching_cp_entry(pool, pool_index, THREAD)) {
bool matched = is_matching_cp_entry(pool, pool_index, CHECK);
if (matched) {
found = true;
CallInfo info;
bool is_done = bootstrap_specifier.resolve_previously_linked_invokedynamic(info, THREAD);
bool is_done = bootstrap_specifier.resolve_previously_linked_invokedynamic(info, CHECK);
if (!is_done) {
// resolve it
Handle recv;
LinkResolver::resolve_invoke(info, recv, pool, indy_index, Bytecodes::_invokedynamic, THREAD);
LinkResolver::resolve_invoke(info, recv, pool, indy_index, Bytecodes::_invokedynamic, CHECK);
break;
}
cpce->set_dynamic_call(pool, info);
if (HAS_PENDING_EXCEPTION) {
ResourceMark rm(THREAD);
tty->print("resolve_indy for class %s has", class_name_symbol->as_C_string());
oop message = java_lang_Throwable::message(PENDING_EXCEPTION);
if (message != NULL) {
char* ex_msg = java_lang_String::as_utf8_string(message);
tty->print_cr(" exception pending '%s %s'",
PENDING_EXCEPTION->klass()->external_name(), ex_msg);
} else {
tty->print_cr(" exception pending %s ",
PENDING_EXCEPTION->klass()->external_name());
}
exit(1);
}
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 2021, 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
@ -114,6 +114,7 @@ class ClassListParser : public StackObj {
bool is_matching_cp_entry(constantPoolHandle &pool, int cp_index, TRAPS);
void resolve_indy(Symbol* class_name_symbol, TRAPS);
void resolve_indy_impl(Symbol* class_name_symbol, TRAPS);
public:
ClassListParser(const char* file);
~ClassListParser();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2021, 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
@ -406,15 +406,14 @@ void ConstantPool::remove_unshareable_info() {
_flags |= (_on_stack | _is_shared);
int num_klasses = 0;
for (int index = 1; index < length(); index++) { // Index 0 is unused
if (!DynamicDumpSharedSpaces) {
assert(!tag_at(index).is_unresolved_klass_in_error(), "This must not happen during static dump time");
} else {
if (tag_at(index).is_unresolved_klass_in_error() ||
tag_at(index).is_method_handle_in_error() ||
tag_at(index).is_method_type_in_error() ||
tag_at(index).is_dynamic_constant_in_error()) {
tag_at_put(index, JVM_CONSTANT_UnresolvedClass);
}
if (tag_at(index).is_unresolved_klass_in_error()) {
tag_at_put(index, JVM_CONSTANT_UnresolvedClass);
} else if (tag_at(index).is_method_handle_in_error()) {
tag_at_put(index, JVM_CONSTANT_MethodHandle);
} else if (tag_at(index).is_method_type_in_error()) {
tag_at_put(index, JVM_CONSTANT_MethodType);
} else if (tag_at(index).is_dynamic_constant_in_error()) {
tag_at_put(index, JVM_CONSTANT_Dynamic);
}
if (tag_at(index).is_klass()) {
// This class was resolved as a side effect of executing Java code

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2013, 2021, 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
@ -336,6 +336,7 @@ hotspot_appcds_dynamic = \
-runtime/cds/appcds/LambdaEagerInit.java \
-runtime/cds/appcds/LambdaProxyClasslist.java \
-runtime/cds/appcds/LambdaVerificationFailedDuringDump.java \
-runtime/cds/appcds/LambdaWithOldClass.java \
-runtime/cds/appcds/LongClassListPath.java \
-runtime/cds/appcds/LotsOfClasses.java \
-runtime/cds/appcds/NonExistClasspath.java \

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2021, 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
@ -44,7 +44,7 @@ public class BadBSM {
TestCommon.list("WrongBSM",
"@lambda-proxy WrongBSM 7"),
"-Xlog:cds+lambda=debug");
out.shouldHaveExitValue(0);
out.shouldContain( "is_supported_invokedynamic check failed for cp_index 7");
out.shouldHaveExitValue(0)
.shouldContain("resolve_indy for class WrongBSM has encountered exception: java.lang.NoSuchMethodError");
}
}

View File

@ -0,0 +1,80 @@
/*
* Copyright (c) 2021, 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 8259275
* @summary VM should not crash during CDS dump and run time when a lambda
* expression references an old version of class.
* @requires vm.cds
* @library /test/lib
* @compile test-classes/OldClass.jasm
* @compile test-classes/LambdaWithOldClassApp.java
* @run driver LambdaWithOldClass
*/
import jdk.test.lib.cds.CDSOptions;
import jdk.test.lib.cds.CDSTestUtils;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
public class LambdaWithOldClass {
public static void main(String[] args) throws Exception {
String mainClass = "LambdaWithOldClassApp";
String namePrefix = "lambdawitholdclass";
JarBuilder.build(namePrefix, mainClass, "OldClass", "TestInterface");
String appJar = TestCommon.getTestJar(namePrefix + ".jar");
String classList = namePrefix + ".list";
String archiveName = namePrefix + ".jsa";
// dump class list
ProcessBuilder pb = ProcessTools.createTestJvm(
"-XX:DumpLoadedClassList=" + classList,
"-cp", appJar,
mainClass);
OutputAnalyzer output = TestCommon.executeAndLog(pb, namePrefix);
output.shouldHaveExitValue(0);
// create archive with the class list
CDSOptions opts = (new CDSOptions())
.addPrefix("-XX:ExtraSharedClassListFile=" + classList,
"-cp", appJar,
"-Xlog:class+load,cds")
.setArchiveName(archiveName);
CDSTestUtils.createArchiveAndCheck(opts);
// run with archive
CDSOptions runOpts = (new CDSOptions())
.addPrefix("-cp", appJar, "-Xlog:class+load,cds=debug")
.setArchiveName(archiveName)
.setUseVersion(false)
.addSuffix(mainClass);
output = CDSTestUtils.runWithArchive(runOpts);
output.shouldContain("[class,load] LambdaWithOldClassApp source: shared objects file")
.shouldMatch(".class.load. LambdaWithOldClassApp[$][$]Lambda[$].*/0x.*source:.*LambdaWithOldClassApp")
.shouldHaveExitValue(0);
}
}

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2021, 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.
*
*/
interface TestInterface {
public void apply(OldClass c);
}
public class LambdaWithOldClassApp {
public static void main(String args[]) {
doit((c) -> {
System.out.println("c = " + c);
});
}
static void doit(TestInterface i) {
OldClass c = new OldClass();
i.apply(c);
}
}

View File

@ -0,0 +1,37 @@
/*
* Copyright (c) 2021, 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.
*
*/
super class OldClass
version 49:0
{
Method "<init>":"()V"
stack 1 locals 1
{
aload_0;
invokespecial Method java/lang/Object."<init>":"()V";
return;
}
} // end Class OldClass