Skip to content

Commit 9a19a0c

Browse files
Wang HuangWu Yan
authored and
Harold Seigel
committedMay 7, 2021
8264760: JVM crashes when two threads encounter the same resolution error
Co-authored-by: Wang Huang <whuang@openjdk.org> Co-authored-by: Wu Yan <wuyan34@huawei.com> Reviewed-by: dholmes, hseigel
1 parent 14f0afe commit 9a19a0c

File tree

4 files changed

+285
-2
lines changed

4 files changed

+285
-2
lines changed
 

‎src/hotspot/share/classfile/systemDictionary.cpp

+5-2
Original file line numberDiff line numberDiff line change
@@ -1922,8 +1922,11 @@ void SystemDictionary::add_nest_host_error(const constantPoolHandle& pool,
19221922
{
19231923
MutexLocker ml(Thread::current(), SystemDictionary_lock);
19241924
ResolutionErrorEntry* entry = resolution_errors()->find_entry(index, hash, pool, which);
1925-
if (entry != NULL) {
1926-
assert(entry->nest_host_error() == NULL, "Nest host error message already set!");
1925+
if (entry != NULL && entry->nest_host_error() == NULL) {
1926+
// An existing entry means we had a true resolution failure (LinkageError) with our nest host, but we
1927+
// still want to add the error message for the higher-level access checks to report. We should
1928+
// only reach here under the same error condition, so we can ignore the potential race with setting
1929+
// the message. If we see it is already set then we can ignore it.
19271930
entry->set_nest_host_error(message);
19281931
} else {
19291932
resolution_errors()->add_entry(index, hash, pool, which, message);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/*
2+
* Copyright (c) 2021, Huawei Technologies Co., Ltd. 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+
* This class was used to produce a jcod file in which the
26+
* NestMembers attribute was modified to make it empty. Class
27+
* HostNoNestMember$Member has class HostNoNestMember as its
28+
* NestHost, which will trigger an error when resolving.
29+
*
30+
* When compiled, this generates a HostNoNestMember class and
31+
* a HostNoNestMember$Menber class. The former class, HostNoNestMember,
32+
* gets overwritten when HostNoNestMember.jcod gets compiled.
33+
*/
34+
class HostNoNestMember {
35+
class Member {
36+
private int value;
37+
}
38+
39+
public int test() {
40+
Member m = new Member();
41+
return m.value;
42+
}
43+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
/*
2+
* Copyright (c) 2021, Huawei Technologies Co., Ltd. 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+
// NestMembers attribute empty
25+
26+
class HostNoNestMember {
27+
0xCAFEBABE;
28+
0; // minor version
29+
60; // version
30+
[] { // Constant Pool
31+
; // first element is empty
32+
Method #2 #3; // #1
33+
class #4; // #2
34+
NameAndType #5 #6; // #3
35+
Utf8 "java/lang/Object"; // #4
36+
Utf8 "<init>"; // #5
37+
Utf8 "()V"; // #6
38+
class #8; // #7
39+
Utf8 "HostNoNestMember$Member"; // #8
40+
Method #7 #10; // #9
41+
NameAndType #5 #11; // #10
42+
Utf8 "(LHostNoNestMember;)V"; // #11
43+
Field #7 #13; // #12
44+
NameAndType #14 #15; // #13
45+
Utf8 "value"; // #14
46+
Utf8 "I"; // #15
47+
class #17; // #16
48+
Utf8 "HostNoNestMember"; // #17
49+
Utf8 "Code"; // #18
50+
Utf8 "LineNumberTable"; // #19
51+
Utf8 "test"; // #20
52+
Utf8 "()I"; // #21
53+
Utf8 "SourceFile"; // #22
54+
Utf8 "TestNestHostErrorWithMultiThread.java"; // #23
55+
Utf8 "NestMembers"; // #24
56+
Utf8 "InnerClasses"; // #25
57+
Utf8 "Member"; // #26
58+
} // Constant Pool
59+
60+
0x0020; // access
61+
#16;// this_cpx
62+
#2;// super_cpx
63+
64+
[] { // Interfaces
65+
} // Interfaces
66+
67+
[] { // Fields
68+
} // Fields
69+
70+
[] { // Methods
71+
{ // method
72+
0x0000; // access
73+
#5; // name_index
74+
#6; // descriptor_index
75+
[] { // Attributes
76+
Attr(#18) { // Code
77+
1; // max_stack
78+
1; // max_locals
79+
Bytes[]{
80+
0x2AB70001B1;
81+
}
82+
[] { // Traps
83+
} // end Traps
84+
[] { // Attributes
85+
Attr(#19) { // LineNumberTable
86+
[] { // line_number_table
87+
0 44;
88+
}
89+
} // end LineNumberTable
90+
} // Attributes
91+
} // end Code
92+
} // Attributes
93+
}
94+
;
95+
{ // method
96+
0x0001; // access
97+
#20; // name_index
98+
#21; // descriptor_index
99+
[] { // Attributes
100+
Attr(#18) { // Code
101+
3; // max_stack
102+
2; // max_locals
103+
Bytes[]{
104+
0xBB0007592AB70009;
105+
0x4C2BB4000CAC;
106+
}
107+
[] { // Traps
108+
} // end Traps
109+
[] { // Attributes
110+
Attr(#19) { // LineNumberTable
111+
[] { // line_number_table
112+
0 50;
113+
9 51;
114+
}
115+
} // end LineNumberTable
116+
} // Attributes
117+
} // end Code
118+
} // Attributes
119+
}
120+
} // Methods
121+
122+
[] { // Attributes
123+
Attr(#22) { // SourceFile
124+
#23;
125+
} // end SourceFile
126+
;
127+
Attr(#24) { // NestMembers
128+
[] { // classes
129+
// #7; delete NestMember
130+
}
131+
} // end NestMembers
132+
;
133+
Attr(#25) { // InnerClasses
134+
[] { // classes
135+
#7 #16 #26 0;
136+
}
137+
} // end InnerClasses
138+
} // Attributes
139+
} // end class HostNoNestMember
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
* Copyright (c) 2021, Huawei Technologies Co., Ltd. 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+
* @test
26+
* @bug 8264760
27+
* @summary JVM crashes when two threads encounter the same resolution error
28+
*
29+
* @compile HostNoNestMember.java
30+
* @compile HostNoNestMember.jcod
31+
*
32+
* @run main TestNestHostErrorWithMultiThread
33+
*/
34+
35+
// HostNoNestMember.jcod must be compiled after HostNoNestMember.java
36+
// because the class file from the jcod file must replace the
37+
// HostNoNestMember class file generated from HostNoNestMember.java.
38+
39+
import java.util.concurrent.CountDownLatch;
40+
41+
public class TestNestHostErrorWithMultiThread {
42+
43+
public static void main(String args[]) {
44+
CountDownLatch runLatch = new CountDownLatch(1);
45+
CountDownLatch startLatch = new CountDownLatch(2);
46+
47+
Runnable test = new Test(runLatch, startLatch);
48+
49+
Thread t1 = new Thread(test);
50+
Thread t2 = new Thread(test);
51+
52+
t1.start();
53+
t2.start();
54+
55+
try {
56+
// waiting thread creation
57+
startLatch.await();
58+
runLatch.countDown();
59+
60+
t1.join();
61+
t2.join();
62+
} catch (InterruptedException e) {
63+
throw new Error("Unexpected interrupt");
64+
}
65+
}
66+
67+
static class Test implements Runnable {
68+
private CountDownLatch runLatch;
69+
private CountDownLatch startLatch;
70+
71+
Test(CountDownLatch runLatch, CountDownLatch startLatch) {
72+
this.runLatch = runLatch;
73+
this.startLatch = startLatch;
74+
}
75+
76+
@Override
77+
public void run() {
78+
try {
79+
startLatch.countDown();
80+
// Try to have all threads trigger the nesthost check at the same time
81+
runLatch.await();
82+
HostNoNestMember h = new HostNoNestMember();
83+
h.test();
84+
throw new Error("IllegalAccessError was not thrown as expected");
85+
} catch (IllegalAccessError expected) {
86+
String msg = "current type is not listed as a nest member";
87+
if (!expected.getMessage().contains(msg)) {
88+
throw new Error("Wrong " + expected.getClass().getSimpleName() +": \"" +
89+
expected.getMessage() + "\" does not contain \"" +
90+
msg + "\"", expected);
91+
}
92+
System.out.println("OK - got expected exception: " + expected);
93+
} catch (InterruptedException e) {
94+
throw new Error("Unexpected interrupt");
95+
}
96+
}
97+
}
98+
}

1 commit comments

Comments
 (1)

openjdk-notifier[bot] commented on May 7, 2021

@openjdk-notifier[bot]
Please sign in to comment.