Skip to content

Commit 5d54bf5

Browse files
committed
8274944: AppCDS dump causes SEGV in VM thread while adjusting lambda proxy class info
Reviewed-by: stuefe Backport-of: e5cd2692da6327c6fde954f86595a08fe5edf43f
1 parent e459c8c commit 5d54bf5

File tree

9 files changed

+248
-0
lines changed

9 files changed

+248
-0
lines changed

src/hotspot/share/cds/dynamicArchive.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ class DynamicArchiveBuilder : public ArchiveBuilder {
111111
// Block concurrent class unloading from changing the _dumptime_table
112112
MutexLocker ml(DumpTimeTable_lock, Mutex::_no_safepoint_check_flag);
113113
SystemDictionaryShared::check_excluded_classes();
114+
SystemDictionaryShared::cleanup_lambda_proxy_class_dictionary();
114115

115116
init_header();
116117
gather_source_objs();

src/hotspot/share/cds/metaspaceShared.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,7 @@ void VM_PopulateDumpSharedSpace::doit() {
487487
// Block concurrent class unloading from changing the _dumptime_table
488488
MutexLocker ml(DumpTimeTable_lock, Mutex::_no_safepoint_check_flag);
489489
SystemDictionaryShared::check_excluded_classes();
490+
SystemDictionaryShared::cleanup_lambda_proxy_class_dictionary();
490491

491492
StaticArchiveBuilder builder;
492493
builder.gather_source_objs();

src/hotspot/share/classfile/systemDictionaryShared.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2405,6 +2405,28 @@ bool SystemDictionaryShared::empty_dumptime_table() {
24052405
return false;
24062406
}
24072407

2408+
class CleanupDumpTimeLambdaProxyClassTable: StackObj {
2409+
public:
2410+
bool do_entry(LambdaProxyClassKey& key, DumpTimeLambdaProxyClassInfo& info) {
2411+
assert_lock_strong(DumpTimeTable_lock);
2412+
for (int i = 0; i < info._proxy_klasses->length(); i++) {
2413+
InstanceKlass* ik = info._proxy_klasses->at(i);
2414+
if (!ik->can_be_verified_at_dumptime()) {
2415+
info._proxy_klasses->remove_at(i);
2416+
}
2417+
}
2418+
return info._proxy_klasses->length() == 0 ? true /* delete the node*/ : false;
2419+
}
2420+
};
2421+
2422+
void SystemDictionaryShared::cleanup_lambda_proxy_class_dictionary() {
2423+
assert_lock_strong(DumpTimeTable_lock);
2424+
if (_dumptime_lambda_proxy_class_dictionary != NULL) {
2425+
CleanupDumpTimeLambdaProxyClassTable cleanup_proxy_classes;
2426+
_dumptime_lambda_proxy_class_dictionary->unlink(&cleanup_proxy_classes);
2427+
}
2428+
}
2429+
24082430
#if INCLUDE_CDS_JAVA_HEAP
24092431

24102432
class ArchivedMirrorPatcher {

src/hotspot/share/classfile/systemDictionaryShared.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,7 @@ class SystemDictionaryShared: public SystemDictionary {
331331
static size_t estimate_size_for_archive();
332332
static void write_to_archive(bool is_static_archive = true);
333333
static void adjust_lambda_proxy_class_dictionary();
334+
static void cleanup_lambda_proxy_class_dictionary();
334335
static void serialize_dictionary_headers(class SerializeClosure* soc,
335336
bool is_static_archive = true);
336337
static void serialize_vm_classes(class SerializeClosure* soc);

test/hotspot/jtreg/TEST.groups

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,7 @@ hotspot_appcds_dynamic = \
399399
-runtime/cds/appcds/DumpClassList.java \
400400
-runtime/cds/appcds/DumpClassListWithLF.java \
401401
-runtime/cds/appcds/ExtraSymbols.java \
402+
-runtime/cds/appcds/LambdaContainsOldInf.java \
402403
-runtime/cds/appcds/LambdaEagerInit.java \
403404
-runtime/cds/appcds/LambdaProxyClasslist.java \
404405
-runtime/cds/appcds/LambdaVerificationFailedDuringDump.java \
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* Copyright (c) 2021, 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 8274944
28+
* @summary VM should not crash during CDS dump when a lambda proxy class
29+
* contains an old version of interface.
30+
* @requires vm.cds
31+
* @library /test/lib
32+
* @compile test-classes/OldProvider.jasm
33+
* @compile test-classes/LambdaContainsOldInfApp.java
34+
* @run driver LambdaContainsOldInf
35+
*/
36+
37+
import jdk.test.lib.cds.CDSOptions;
38+
import jdk.test.lib.cds.CDSTestUtils;
39+
import jdk.test.lib.process.OutputAnalyzer;
40+
41+
public class LambdaContainsOldInf {
42+
43+
public static void main(String[] args) throws Exception {
44+
String mainClass = "LambdaContainsOldInfApp";
45+
String namePrefix = "lambdacontainsoldinf";
46+
JarBuilder.build(namePrefix, mainClass, "OldProvider");
47+
48+
String appJar = TestCommon.getTestJar(namePrefix + ".jar");
49+
String classList = namePrefix + ".list";
50+
String archiveName = namePrefix + ".jsa";
51+
52+
// dump class list
53+
CDSTestUtils.dumpClassList(classList, "-cp", appJar, mainClass);
54+
55+
// create archive with the class list
56+
CDSOptions opts = (new CDSOptions())
57+
.addPrefix("-XX:ExtraSharedClassListFile=" + classList,
58+
"-cp", appJar,
59+
"-Xlog:class+load,cds")
60+
.setArchiveName(archiveName);
61+
OutputAnalyzer output = CDSTestUtils.createArchiveAndCheck(opts);
62+
TestCommon.checkExecReturn(output, 0, true,
63+
"Skipping OldProvider: Old class has been linked");
64+
output.shouldMatch("Skipping.LambdaContainsOldInfApp[$][$]Lambda[$].*0x.*:.*Old.class.has.been.linked");
65+
66+
// run with archive
67+
CDSOptions runOpts = (new CDSOptions())
68+
.addPrefix("-cp", appJar, "-Xlog:class+load,cds=debug")
69+
.setArchiveName(archiveName)
70+
.setUseVersion(false)
71+
.addSuffix(mainClass);
72+
output = CDSTestUtils.runWithArchive(runOpts);
73+
TestCommon.checkExecReturn(output, 0, true,
74+
"[class,load] LambdaContainsOldInfApp source: shared objects file");
75+
output.shouldMatch(".class.load. OldProvider.source:.*lambdacontainsoldinf.jar")
76+
.shouldMatch(".class.load. LambdaContainsOldInfApp[$][$]Lambda[$].*/0x.*source:.*LambdaContainsOldInf");
77+
}
78+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
* Copyright (c) 2021, 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 8274944
28+
* @summary VM should not crash during CDS dump when a lambda proxy class
29+
* contains an old version of interface.
30+
* @requires vm.cds
31+
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
32+
* /test/hotspot/jtreg/runtime/cds/appcds/test-classes
33+
* /test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes
34+
* @build LambdaContainsOldInfApp sun.hotspot.WhiteBox OldProvider LambdaVerification
35+
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar lambda_contains_old_inf.jar LambdaVerification
36+
* LambdaContainsOldInfApp OldProvider
37+
* @run driver jdk.test.lib.helpers.ClassFileInstaller -jar WhiteBox.jar sun.hotspot.WhiteBox
38+
* @run driver jdk.test.lib.helpers.ClassFileInstaller sun.hotspot.WhiteBox
39+
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. LambdaContainsOldInf
40+
*/
41+
42+
import jdk.test.lib.helpers.ClassFileInstaller;
43+
44+
public class LambdaContainsOldInf extends DynamicArchiveTestBase {
45+
public static void main(String[] args) throws Exception {
46+
runTest(LambdaContainsOldInf::test);
47+
}
48+
49+
static void test() throws Exception {
50+
String topArchiveName = getNewArchiveName();
51+
String appJar = ClassFileInstaller.getJarPath("lambda_contains_old_inf.jar");
52+
String mainClass = "LambdaContainsOldInfApp";
53+
String wbJar = ClassFileInstaller.getJarPath("WhiteBox.jar");
54+
String use_whitebox_jar = "-Xbootclasspath/a:" + wbJar;
55+
56+
dump(topArchiveName,
57+
"-XX:+UnlockDiagnosticVMOptions",
58+
"-XX:+WhiteBoxAPI",
59+
"-Xlog:class+load=debug,cds=debug,cds+dynamic=info",
60+
use_whitebox_jar,
61+
"-cp", appJar, mainClass)
62+
.assertNormalExit(output -> {
63+
output
64+
.shouldMatch("Skipping.LambdaContainsOldInfApp[$][$]Lambda[$].*0x.*:.*Old.class.has.been.linked")
65+
.shouldHaveExitValue(0);
66+
});
67+
68+
run(topArchiveName,
69+
"-XX:+UnlockDiagnosticVMOptions",
70+
"-XX:+WhiteBoxAPI",
71+
use_whitebox_jar,
72+
"-Xlog:class+load=debug",
73+
"-cp", appJar, mainClass)
74+
.assertNormalExit(output -> {
75+
output.shouldContain("[class,load] LambdaContainsOldInfApp source: shared objects file (top)")
76+
.shouldMatch(".class.load. OldProvider.source:.*lambda_contains_old_inf.jar")
77+
.shouldMatch(".class.load. LambdaContainsOldInfApp[$][$]Lambda[$].*/0x.*source:.*LambdaContainsOldInf")
78+
.shouldHaveExitValue(0);
79+
});
80+
}
81+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Copyright (c) 2021, 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+
public class LambdaContainsOldInfApp {
25+
public static void main(final String... args) {
26+
getProvider();
27+
}
28+
29+
public static OldProvider getProvider() {
30+
return () -> {
31+
return null;
32+
};
33+
}
34+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright (c) 2021, 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+
public interface OldProvider
25+
version 49:0
26+
{
27+
public abstract Method get:"()Ljava/lang/Object;";
28+
29+
} // end Class OldProvider

0 commit comments

Comments
 (0)