Skip to content

Commit fa401f3

Browse files
committed
8333805: Replaying compilation with null static final fields results in a crash
Reviewed-by: thartmann, dlong
1 parent 472b935 commit fa401f3

File tree

3 files changed

+135
-44
lines changed

3 files changed

+135
-44
lines changed

src/hotspot/share/ci/ciInstanceKlass.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -661,7 +661,8 @@ class StaticFinalFieldPrinter : public FieldClosure {
661661
ResourceMark rm;
662662
oop mirror = fd->field_holder()->java_mirror();
663663
_out->print("staticfield %s %s %s ", _holder, fd->name()->as_quoted_ascii(), fd->signature()->as_quoted_ascii());
664-
switch (fd->field_type()) {
664+
BasicType field_type = fd->field_type();
665+
switch (field_type) {
665666
case T_BYTE: _out->print_cr("%d", mirror->byte_field(fd->offset())); break;
666667
case T_BOOLEAN: _out->print_cr("%d", mirror->bool_field(fd->offset())); break;
667668
case T_SHORT: _out->print_cr("%d", mirror->short_field(fd->offset())); break;
@@ -682,9 +683,12 @@ class StaticFinalFieldPrinter : public FieldClosure {
682683
case T_OBJECT: {
683684
oop value = mirror->obj_field_acquire(fd->offset());
684685
if (value == nullptr) {
685-
_out->print_cr("null");
686+
if (field_type == T_ARRAY) {
687+
_out->print("%d", -1);
688+
}
689+
_out->cr();
686690
} else if (value->is_instance()) {
687-
assert(fd->field_type() == T_OBJECT, "");
691+
assert(field_type == T_OBJECT, "");
688692
if (value->is_a(vmClasses::String_klass())) {
689693
const char* ascii_value = java_lang_String::as_quoted_ascii(value);
690694
_out->print_cr("\"%s\"", (ascii_value != nullptr) ? ascii_value : "");

src/hotspot/share/ci/ciReplay.cpp

Lines changed: 46 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,46 +1056,48 @@ class CompileReplay : public StackObj {
10561056
int length = parse_int("array length");
10571057
oop value = nullptr;
10581058

1059-
if (field_signature[1] == JVM_SIGNATURE_ARRAY) {
1060-
// multi dimensional array
1061-
ArrayKlass* kelem = (ArrayKlass *)parse_klass(CHECK);
1062-
if (kelem == nullptr) {
1063-
return;
1064-
}
1065-
int rank = 0;
1066-
while (field_signature[rank] == JVM_SIGNATURE_ARRAY) {
1067-
rank++;
1068-
}
1069-
jint* dims = NEW_RESOURCE_ARRAY(jint, rank);
1070-
dims[0] = length;
1071-
for (int i = 1; i < rank; i++) {
1072-
dims[i] = 1; // These aren't relevant to the compiler
1073-
}
1074-
value = kelem->multi_allocate(rank, dims, CHECK);
1075-
} else {
1076-
if (strcmp(field_signature, "[B") == 0) {
1077-
value = oopFactory::new_byteArray(length, CHECK);
1078-
} else if (strcmp(field_signature, "[Z") == 0) {
1079-
value = oopFactory::new_boolArray(length, CHECK);
1080-
} else if (strcmp(field_signature, "[C") == 0) {
1081-
value = oopFactory::new_charArray(length, CHECK);
1082-
} else if (strcmp(field_signature, "[S") == 0) {
1083-
value = oopFactory::new_shortArray(length, CHECK);
1084-
} else if (strcmp(field_signature, "[F") == 0) {
1085-
value = oopFactory::new_floatArray(length, CHECK);
1086-
} else if (strcmp(field_signature, "[D") == 0) {
1087-
value = oopFactory::new_doubleArray(length, CHECK);
1088-
} else if (strcmp(field_signature, "[I") == 0) {
1089-
value = oopFactory::new_intArray(length, CHECK);
1090-
} else if (strcmp(field_signature, "[J") == 0) {
1091-
value = oopFactory::new_longArray(length, CHECK);
1092-
} else if (field_signature[0] == JVM_SIGNATURE_ARRAY &&
1093-
field_signature[1] == JVM_SIGNATURE_CLASS) {
1094-
parse_klass(CHECK); // eat up the array class name
1095-
Klass* kelem = resolve_klass(field_signature + 1, CHECK);
1096-
value = oopFactory::new_objArray(kelem, length, CHECK);
1059+
if (length != -1) {
1060+
if (field_signature[1] == JVM_SIGNATURE_ARRAY) {
1061+
// multi dimensional array
1062+
ArrayKlass* kelem = (ArrayKlass *)parse_klass(CHECK);
1063+
if (kelem == nullptr) {
1064+
return;
1065+
}
1066+
int rank = 0;
1067+
while (field_signature[rank] == JVM_SIGNATURE_ARRAY) {
1068+
rank++;
1069+
}
1070+
jint* dims = NEW_RESOURCE_ARRAY(jint, rank);
1071+
dims[0] = length;
1072+
for (int i = 1; i < rank; i++) {
1073+
dims[i] = 1; // These aren't relevant to the compiler
1074+
}
1075+
value = kelem->multi_allocate(rank, dims, CHECK);
10971076
} else {
1098-
report_error("unhandled array staticfield");
1077+
if (strcmp(field_signature, "[B") == 0) {
1078+
value = oopFactory::new_byteArray(length, CHECK);
1079+
} else if (strcmp(field_signature, "[Z") == 0) {
1080+
value = oopFactory::new_boolArray(length, CHECK);
1081+
} else if (strcmp(field_signature, "[C") == 0) {
1082+
value = oopFactory::new_charArray(length, CHECK);
1083+
} else if (strcmp(field_signature, "[S") == 0) {
1084+
value = oopFactory::new_shortArray(length, CHECK);
1085+
} else if (strcmp(field_signature, "[F") == 0) {
1086+
value = oopFactory::new_floatArray(length, CHECK);
1087+
} else if (strcmp(field_signature, "[D") == 0) {
1088+
value = oopFactory::new_doubleArray(length, CHECK);
1089+
} else if (strcmp(field_signature, "[I") == 0) {
1090+
value = oopFactory::new_intArray(length, CHECK);
1091+
} else if (strcmp(field_signature, "[J") == 0) {
1092+
value = oopFactory::new_longArray(length, CHECK);
1093+
} else if (field_signature[0] == JVM_SIGNATURE_ARRAY &&
1094+
field_signature[1] == JVM_SIGNATURE_CLASS) {
1095+
Klass* actual_array_klass = parse_klass(CHECK);
1096+
Klass* kelem = ObjArrayKlass::cast(actual_array_klass)->element_klass();
1097+
value = oopFactory::new_objArray(kelem, length, CHECK);
1098+
} else {
1099+
report_error("unhandled array staticfield");
1100+
}
10991101
}
11001102
}
11011103
java_mirror->obj_field_put(fd.offset(), value);
@@ -1133,8 +1135,11 @@ class CompileReplay : public StackObj {
11331135
Handle value = java_lang_String::create_from_str(string_value, CHECK);
11341136
java_mirror->obj_field_put(fd.offset(), value());
11351137
} else if (field_signature[0] == JVM_SIGNATURE_CLASS) {
1136-
Klass* k = resolve_klass(string_value, CHECK);
1137-
oop value = InstanceKlass::cast(k)->allocate_instance(CHECK);
1138+
oop value = nullptr;
1139+
if (string_value != nullptr) {
1140+
Klass* k = resolve_klass(string_value, CHECK);
1141+
value = InstanceKlass::cast(k)->allocate_instance(CHECK);
1142+
}
11381143
java_mirror->obj_field_put(fd.offset(), value);
11391144
} else {
11401145
report_error("unhandled staticfield");
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/*
2+
* Copyright (c) 2024, Red Hat, Inc. 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 8333805
27+
* @library / /test/lib
28+
* @summary Replaying compilation with null static final fields results in a crash
29+
* @requires vm.flightRecorder != true & vm.compMode != "Xint" & vm.compMode != "Xcomp" & vm.debug == true & vm.compiler2.enabled
30+
* @modules java.base/jdk.internal.misc
31+
* @build jdk.test.whitebox.WhiteBox
32+
* @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
33+
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
34+
* compiler.ciReplay.TestNullStaticField
35+
*/
36+
37+
package compiler.ciReplay;
38+
39+
public class TestNullStaticField extends DumpReplayBase {
40+
41+
public static void main(String[] args) {
42+
new TestNullStaticField().runTest(TIERED_DISABLED_VM_OPTION);
43+
}
44+
45+
@Override
46+
public void testAction() {
47+
positiveTest(TIERED_DISABLED_VM_OPTION, "-XX:+ReplayIgnoreInitErrors");
48+
}
49+
50+
@Override
51+
public String getTestClass() {
52+
return TestClassNullStaticField.class.getName();
53+
}
54+
55+
}
56+
57+
class TestClassNullStaticField {
58+
59+
static final Object[] staticNullArrayField = null;
60+
static final Object[][] staticNullMultiArrayField = null;
61+
static final Object staticNullObjectField = null;
62+
static final String staticNullStringField = null;
63+
static final int[] staticNullIntArrayField = null;
64+
static final Object[] staticNotNullArrayField = new A[10];
65+
static final Object[][] staticNotNullMultiArrayField = new A[10][10];
66+
static final Object staticNotNullObjectField = new A();
67+
static final String staticNotNullStringField = "Not null";
68+
static final int[] staticNotNullIntArrayField = new int[10];
69+
70+
public static void main(String[] args) {
71+
for (int i = 0; i < 20_000; i++) {
72+
test();
73+
}
74+
}
75+
public static void test() {
76+
77+
}
78+
79+
private static class A {
80+
}
81+
}
82+

0 commit comments

Comments
 (0)