8259275: JRuby crashes while resolving invokedynamic instruction
Reviewed-by: iklam, minqi, lfoltan
This commit is contained in:
parent
1cf2378bda
commit
15dd8f3aa4
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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 \
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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
|
Loading…
Reference in New Issue
Block a user