Details
-
Bug
-
Resolution: Fixed
-
P2
-
8, 9
-
b167
-
generic
-
generic
-
Verified
Backports
Issue | Fix Version | Assignee | Priority | Status | Resolution | Resolved In Build |
---|---|---|---|---|---|---|
JDK-8179755 | 10 | Igor Veresov | P2 | Resolved | Fixed | b07 |
JDK-8190592 | 8u171 | David Buck | P2 | Resolved | Fixed | b01 |
JDK-8185275 | 8u162 | David Buck | P2 | Closed | Fixed | b01 |
JDK-8198044 | emb-8u171 | David Buck | P2 | Resolved | Fixed | b01 |
Description
FULL PRODUCT VERSION :
$ java -version
java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) Server VM (build 25.121-b13, mixed mode)
FULL OS VERSION :
Linux localhost.localdomain 3.10.0-327.36.2.el7.x86_64 #1 SMP Mon Oct 10 23:08:37 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
A DESCRIPTION OF THE PROBLEM :
The attached testcase fails when run in compiled mode on 32 bit Intel Linux.
It does NOT fail in interpreted mode (-Xint) or in compiled mode with a 64 bit VM.
It does NOT fail on 32 bit Intel Windows.
The testcase has taken significant effort to extract. We have a COBOL product (NTT DATA Enterprise COBOL, formerly Dell Enterprise COBOL) that translates COBOL to Java for execution and the problem originates from a customer COBOL program.
The slightly unusual coding patterns reflect our implementation of COBOL "unsigned usage display" numerics, in which a decimal number is represented in memory using ASCII digits, i.e that characters '0', '1', ... (This also necessitates our use of 'Unsafe')
THE PROBLEM WAS REPRODUCIBLE WITH -Xint FLAG: No
THE PROBLEM WAS REPRODUCIBLE WITH -server FLAG: Yes
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile the code:
$ javac Sim.java Chunk.java
Execute 'Sim'
$ java Sim
EXPECTED VERSUS ACTUAL BEHAVIOR :
$ java Sim
Output is as follows:
main() >
[0000000000]
[0000000001]
[0000000002]
[0000000003]
[0000000004]
[0000000005]
[0000000006]
[0000000007]
[0000000008]
[0000000009]
...
[0000110638]
[0000110639]
[0000110640]
[0000110641]
[0000000000]
[0000000000]
[0000000000]
...
[0000000000]
[0000000000]
[0000000000]
main() <
The output should just be an increasing integer, as can be seen by using -Xint:
java -Xint Sim:
main() >
[0000000000]
[0000000001]
[0000000002]
[0000000003]
[0000000004]
[0000000005]
[0000000006]
[0000000007]
[0000000008]
[0000000009]
...
[0000198760]
[0000198761]
[0000198762]
[0000198763]
[0000198764]
main() <
The exact point in the failing case where the error occurs (output turns to zero) seems to vary, and I assume corresponds to when HotSpot compilation occurs
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
Sim.java:
public class Sim {
private final Chunk c_A1;
private final Chunk c_A2;
private final Chunk c_R;
public static void main(String[] args) {
System.out.println("main() >");
Sim s = new Sim();
s.go();
System.out.println("main() <");
}
public Sim() {
Chunk r_0 = new Chunk(64);
c_A1 = r_0.slice(0, 11);
c_A2 = r_0.slice(11, 11);
c_R = r_0.slice(22, 19);
}
private void go() {
c_A1.fillSmall(0, 11, (byte)0x30);
for (long i = 0; i < 198765L; i++) {
c_A2.put_Long_DU(0, 11, i );
c_R.fillSmall(9, 10, (byte)0x30);
c_R.put_Long_DU(9, 10, c_R.get_DU_Long(9, 10) + c_A2.get_DU_Long(0, 11));
c_R.put_Long_DU(9, 10, c_R.get_DU_Long(9, 10) + c_A1.get_DU_Long(0, 11));
printR();
}
}
private void printR() {
final byte[] ba = c_R.getAsByteArray(9, 10);
final String s = new String(ba);
System.out.println("[" + s + "]");
}
}
Chunk.java:
import java.lang.reflect.Field;
import sun.misc.Unsafe;
public class Chunk {
private static final Unsafe UNSAFE;
private final long baseAddress;
private final int length;
static {
Unsafe u = null;
try {
final Class<Unsafe> uc = Unsafe.class;
final Field field = uc.getDeclaredField("theUnsafe");
field.setAccessible(true);
u = (Unsafe) field.get(uc);
} catch (NoSuchFieldException | IllegalAccessException | RuntimeException ex) {
ex.printStackTrace();
}
UNSAFE = u;
}
public Chunk(int length) {
baseAddress = UNSAFE.allocateMemory(length);
this.length = length;
}
public final long getBaseAddress() {
return baseAddress;
}
public final int getLength() {
return length;
}
protected Chunk(Chunk oc, int op, int ol) {
baseAddress = oc.getBaseAddress() + op;
if (oc.getLength() == -1) {
length = -1;
} else {
length = Math.min(ol, oc.getLength() - op);
}
}
public Chunk slice(int p, int l) {
Chunk o = new Chunk(this, p, l);
return o;
}
public final void fillSmall(int tp, int tl, byte b) {
long p = baseAddress + tp;
for (int i = 0; i < tl; i++) {
UNSAFE.putByte(p++, b);
}
}
public void put_Long_DU(int p, int d, long v) {
long a = baseAddress + p;
for (int i = d - 1; i >= 0; i--) {
long b = (v % 10) + 0x30;
UNSAFE.putByte(a + i, (byte) b);
v /= 10;
}
}
public long get_DU_Long(int p, int l) {
long a = baseAddress + p;
long ret = 0;
for (int i = 0; i < l; i++) {
final int b = UNSAFE.getByte(a++);
ret *= 10;
ret += b & 0x0f;
}
return ret;
}
public byte[] getAsByteArray(int p, int l) {
byte[] ret = new byte[l];
long a = baseAddress + p;
for (int i = 0; i < l; i++) {
ret[i] = UNSAFE.getByte(a++);
}
return ret;
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
End customer has had to change their original COBOL program to avoid generating the pattern that causes this issue. They have had to do this in multiple programs.
$ java -version
java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) Server VM (build 25.121-b13, mixed mode)
FULL OS VERSION :
Linux localhost.localdomain 3.10.0-327.36.2.el7.x86_64 #1 SMP Mon Oct 10 23:08:37 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
A DESCRIPTION OF THE PROBLEM :
The attached testcase fails when run in compiled mode on 32 bit Intel Linux.
It does NOT fail in interpreted mode (-Xint) or in compiled mode with a 64 bit VM.
It does NOT fail on 32 bit Intel Windows.
The testcase has taken significant effort to extract. We have a COBOL product (NTT DATA Enterprise COBOL, formerly Dell Enterprise COBOL) that translates COBOL to Java for execution and the problem originates from a customer COBOL program.
The slightly unusual coding patterns reflect our implementation of COBOL "unsigned usage display" numerics, in which a decimal number is represented in memory using ASCII digits, i.e that characters '0', '1', ... (This also necessitates our use of 'Unsafe')
THE PROBLEM WAS REPRODUCIBLE WITH -Xint FLAG: No
THE PROBLEM WAS REPRODUCIBLE WITH -server FLAG: Yes
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile the code:
$ javac Sim.java Chunk.java
Execute 'Sim'
$ java Sim
EXPECTED VERSUS ACTUAL BEHAVIOR :
$ java Sim
Output is as follows:
main() >
[0000000000]
[0000000001]
[0000000002]
[0000000003]
[0000000004]
[0000000005]
[0000000006]
[0000000007]
[0000000008]
[0000000009]
...
[0000110638]
[0000110639]
[0000110640]
[0000110641]
[0000000000]
[0000000000]
[0000000000]
...
[0000000000]
[0000000000]
[0000000000]
main() <
The output should just be an increasing integer, as can be seen by using -Xint:
java -Xint Sim:
main() >
[0000000000]
[0000000001]
[0000000002]
[0000000003]
[0000000004]
[0000000005]
[0000000006]
[0000000007]
[0000000008]
[0000000009]
...
[0000198760]
[0000198761]
[0000198762]
[0000198763]
[0000198764]
main() <
The exact point in the failing case where the error occurs (output turns to zero) seems to vary, and I assume corresponds to when HotSpot compilation occurs
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
Sim.java:
public class Sim {
private final Chunk c_A1;
private final Chunk c_A2;
private final Chunk c_R;
public static void main(String[] args) {
System.out.println("main() >");
Sim s = new Sim();
s.go();
System.out.println("main() <");
}
public Sim() {
Chunk r_0 = new Chunk(64);
c_A1 = r_0.slice(0, 11);
c_A2 = r_0.slice(11, 11);
c_R = r_0.slice(22, 19);
}
private void go() {
c_A1.fillSmall(0, 11, (byte)0x30);
for (long i = 0; i < 198765L; i++) {
c_A2.put_Long_DU(0, 11, i );
c_R.fillSmall(9, 10, (byte)0x30);
c_R.put_Long_DU(9, 10, c_R.get_DU_Long(9, 10) + c_A2.get_DU_Long(0, 11));
c_R.put_Long_DU(9, 10, c_R.get_DU_Long(9, 10) + c_A1.get_DU_Long(0, 11));
printR();
}
}
private void printR() {
final byte[] ba = c_R.getAsByteArray(9, 10);
final String s = new String(ba);
System.out.println("[" + s + "]");
}
}
Chunk.java:
import java.lang.reflect.Field;
import sun.misc.Unsafe;
public class Chunk {
private static final Unsafe UNSAFE;
private final long baseAddress;
private final int length;
static {
Unsafe u = null;
try {
final Class<Unsafe> uc = Unsafe.class;
final Field field = uc.getDeclaredField("theUnsafe");
field.setAccessible(true);
u = (Unsafe) field.get(uc);
} catch (NoSuchFieldException | IllegalAccessException | RuntimeException ex) {
ex.printStackTrace();
}
UNSAFE = u;
}
public Chunk(int length) {
baseAddress = UNSAFE.allocateMemory(length);
this.length = length;
}
public final long getBaseAddress() {
return baseAddress;
}
public final int getLength() {
return length;
}
protected Chunk(Chunk oc, int op, int ol) {
baseAddress = oc.getBaseAddress() + op;
if (oc.getLength() == -1) {
length = -1;
} else {
length = Math.min(ol, oc.getLength() - op);
}
}
public Chunk slice(int p, int l) {
Chunk o = new Chunk(this, p, l);
return o;
}
public final void fillSmall(int tp, int tl, byte b) {
long p = baseAddress + tp;
for (int i = 0; i < tl; i++) {
UNSAFE.putByte(p++, b);
}
}
public void put_Long_DU(int p, int d, long v) {
long a = baseAddress + p;
for (int i = d - 1; i >= 0; i--) {
long b = (v % 10) + 0x30;
UNSAFE.putByte(a + i, (byte) b);
v /= 10;
}
}
public long get_DU_Long(int p, int l) {
long a = baseAddress + p;
long ret = 0;
for (int i = 0; i < l; i++) {
final int b = UNSAFE.getByte(a++);
ret *= 10;
ret += b & 0x0f;
}
return ret;
}
public byte[] getAsByteArray(int p, int l) {
byte[] ret = new byte[l];
long a = baseAddress + p;
for (int i = 0; i < l; i++) {
ret[i] = UNSAFE.getByte(a++);
}
return ret;
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
End customer has had to change their original COBOL program to avoid generating the pattern that causes this issue. They have had to do this in multiple programs.
Attachments
Issue Links
- backported by
-
JDK-8179755 Aliasing problem with raw memory accesses
- Resolved
-
JDK-8190592 Aliasing problem with raw memory accesses
- Resolved
-
JDK-8198044 Aliasing problem with raw memory accesses
- Resolved
-
JDK-8185275 Aliasing problem with raw memory accesses
- Closed
- duplicates
-
JDK-8185029 Incorrect result from program when JIT takes effect
- Closed
-
JDK-8183398 Another occurence of JDK-8178047
- Closed
(1 duplicates)