-
Bug
-
Resolution: Fixed
-
P3
-
8, 9, 10, 11, 12
-
b19
-
generic
-
generic
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8225103 | 11.0.5-oracle | Rahul Raghavan | P3 | Resolved | Fixed | b01 |
JDK-8225416 | 11.0.5 | Rahul Raghavan | P3 | Resolved | Fixed | b01 |
JDK-8225119 | 11.0.4 | Rahul Raghavan | P3 | Resolved | Fixed | b06 |
JDK-8224921 | openjdk8u222 | Rahul Raghavan | P3 | Resolved | Fixed | b05 |
JDK-8225230 | 8u231 | Fairoz Matte | P3 | Resolved | Fixed | b01 |
JDK-8229562 | emb-8u231 | Fairoz Matte | P3 | Resolved | Fixed | b01 |
CentOS 7.2 / Ubuntu 14.04
A DESCRIPTION OF THE PROBLEM :
Generally speaking, this a problem that the primitive array length changes when Unsafe.putInt is following the array creation.
This problem happens in all our test jvm (7u91, 8u132 (openjdk), 8u172, 10.0.1)
The core problem code can be simplified as:
byte[] buf = new byte[397];
THE_UNSAFE.putInt(buf, BYTE_ARRAY_BASE_OFFSET + 1, buf.length);
After these code, buf.length "should" never be changed.
But the length really changes on some running of multiple executions.
Under default settings with hotspot jvm (no user defined options provided),
the problem can be reproduced occasionally.
Under extra option provided (-XX:CompileOnly=JvmTest.serBytes),
the problem can always be reproduces.
With openjdk hotspot jvm with ASSERT enabled, (my jdk8 build is 8u132)
the jvm crash with following information:
# A fatal error has been detected by the Java Runtime Environment:
#
# Internal Error (/root/lty/jdk8/openjdk/hotspot/src/share/vm/opto/memnode.cpp:2883), pid=19749, tid=140692759176960
# assert((end_offset % BytesPerInt) == 0) failed: odd end offset
#
For your convenience, our analysis shows the problem may relate to array InitializeNode logic.
It `capture_store` the the memory write of Unsafe.putInt.
Since the putInt occupied offset range [17, 21] from the array pointer,
then it decided to `clear_memory` of offset range [16, 17] of the array pointer.
This range actually cannot pass the assert "assert((end_offset % BytesPerInt) == 0, "odd end offset")".
While in jvm product mode, without the assert, the compiler falsely calculated to clear range [13, 17],
which will clear the three most significant bytes of the `length` of this array.
In the example code, byte array with length 397 (0x0000018d) becomes length 141 (0x0000008d).
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the java code multiple times
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
(Output nothing)
ACTUAL -
Occasionally output multiple lines:
"array length internal error, expected: 397 (0x18d) actual: 141 (0x8d)"
---------- BEGIN SOURCE ----------
import sun.misc.Unsafe;
import java.lang.reflect.Field;
import java.security.AccessController;
import java.security.PrivilegedAction;
public class JvmTest {
public static void main(String[] args) {
System.err.close();
int count = 0;
while (count++ < 120000) {
test();
}
}
public static void test() {
byte[] newBuf = serBytes(397);
if (newBuf.length != 397) {
System.out.println("array length internal error, expected: " +
397 + " (0x" + Integer.toHexString(397) + ")"
+ " actual: " + newBuf.length
+ " (0x" + Integer.toHexString(newBuf.length) + ")");
}
}
public static byte[] serBytes(int bufLen) {
byte[] buf = new byte[bufLen];
THE_UNSAFE.putInt(buf, BYTE_ARRAY_BASE_OFFSET + 1, buf.length);
System.err.println("ref " + buf);
return buf;
}
/*
Unsafe fields and initialization
*/
static final Unsafe THE_UNSAFE;
static final long BYTE_ARRAY_BASE_OFFSET;
static {
THE_UNSAFE = (Unsafe) AccessController.doPrivileged(
new PrivilegedAction<Object>() {
@Override
public Object run() {
try {
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
return f.get(null);
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new Error();
}
}
}
);
BYTE_ARRAY_BASE_OFFSET = THE_UNSAFE.arrayBaseOffset(byte[].class);
}
}
---------- END SOURCE ----------
FREQUENCY : occasionally
- backported by
-
JDK-8224921 Unsafe write after primitive array creation may result in array length change
- Resolved
-
JDK-8225103 Unsafe write after primitive array creation may result in array length change
- Resolved
-
JDK-8225119 Unsafe write after primitive array creation may result in array length change
- Resolved
-
JDK-8225230 Unsafe write after primitive array creation may result in array length change
- Resolved
-
JDK-8225416 Unsafe write after primitive array creation may result in array length change
- Resolved
-
JDK-8229562 Unsafe write after primitive array creation may result in array length change
- Resolved
- relates to
-
JDK-8225567 Wrong file headers with 8202414 fix changeset
- Resolved