-
Bug
-
Resolution: Unresolved
-
P3
-
11, 17.0.2, 18, 19, 21
-
Cause Known
-
x86
Flight Recording contains stack traces that actually never occured during execution.
--- Example: ArrayListGrow.java ---
import java.util.ArrayList;
import java.util.List;
public class ArrayListGrow {
static final int SIZE = 2048;
static volatile List<Object> tmp;
static void runTest() {
List<Object> list = new ArrayList<>(SIZE);
fill(list);
tmp = list;
}
static void fill(List<Object> list) {
for (int i = 0; i < SIZE; i++) {
list.add(i);
}
}
static void spoil() {
for (int i = 0; i < 1000000; i++) {
new ArrayList<>(0).add("");
}
}
public static void main(String[] args) {
spoil();
while (true) {
runTest();
}
}
}
---
Start
java -XX:+UnlockDiagnosticVMOptions -XX:+DebugNonSafepoints -XX:StartFlightRecording=filename=out.jfr ArrayListGrow
Let it run for ~10 seconds, and then open the produced out.jfr.
It will contain the considerable number of execution samples with the following stack trace:
java.util.ArrayList.grow(int):239
java.util.ArrayList.grow():244
java.util.ArrayList.add(Object, Object[], int):454
java.util.ArrayList.add(Object):467
ArrayListGrow.fill(List):16
ArrayListGrow.runTest():10
ArrayListGrow.main(String[]):30
// see https://cr.openjdk.java.net/~apangin/8281677/img/jfr-screenshot.png
However, this stack trace could not occur during execution, since the ArrayList is created with the sufficient initial size and never grows.
The reason is the wrong PcDesc information in the compiled code. Besides JFR, the problem affects other profiling and benchmarking tools, including async-profiler, perf-map-agent, and JMH. Originally, the issue was raised in async-profiler repository: https://github.com/jvm-profiling-tools/async-profiler/discussions/541
The version I tested:
OpenJDK 64-Bit Server VM (build 18-ea+35-2085, mixed mode, sharing)
I see the same problem on recent builds of JDK 11, but not on JDK 8.
Curiously, if I comment out // spoil() call in the above example, the profile will be correct.
With `-XX:-TieredCompilation`, there is no problem either.
--- Example: ArrayListGrow.java ---
import java.util.ArrayList;
import java.util.List;
public class ArrayListGrow {
static final int SIZE = 2048;
static volatile List<Object> tmp;
static void runTest() {
List<Object> list = new ArrayList<>(SIZE);
fill(list);
tmp = list;
}
static void fill(List<Object> list) {
for (int i = 0; i < SIZE; i++) {
list.add(i);
}
}
static void spoil() {
for (int i = 0; i < 1000000; i++) {
new ArrayList<>(0).add("");
}
}
public static void main(String[] args) {
spoil();
while (true) {
runTest();
}
}
}
---
Start
java -XX:+UnlockDiagnosticVMOptions -XX:+DebugNonSafepoints -XX:StartFlightRecording=filename=out.jfr ArrayListGrow
Let it run for ~10 seconds, and then open the produced out.jfr.
It will contain the considerable number of execution samples with the following stack trace:
java.util.ArrayList.grow(int):239
java.util.ArrayList.grow():244
java.util.ArrayList.add(Object, Object[], int):454
java.util.ArrayList.add(Object):467
ArrayListGrow.fill(List):16
ArrayListGrow.runTest():10
ArrayListGrow.main(String[]):30
// see https://cr.openjdk.java.net/~apangin/8281677/img/jfr-screenshot.png
However, this stack trace could not occur during execution, since the ArrayList is created with the sufficient initial size and never grows.
The reason is the wrong PcDesc information in the compiled code. Besides JFR, the problem affects other profiling and benchmarking tools, including async-profiler, perf-map-agent, and JMH. Originally, the issue was raised in async-profiler repository: https://github.com/jvm-profiling-tools/async-profiler/discussions/541
The version I tested:
OpenJDK 64-Bit Server VM (build 18-ea+35-2085, mixed mode, sharing)
I see the same problem on recent builds of JDK 11, but not on JDK 8.
Curiously, if I comment out // spoil() call in the above example, the profile will be correct.
With `-XX:-TieredCompilation`, there is no problem either.