JDK-4750681 : Bad exception in the copying loop
  • Type: Bug
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 1.4.1,1.4.2
  • Priority: P1
  • Status: Resolved
  • Resolution: Fixed
  • OS: solaris_2.6,solaris_7
  • CPU: generic,sparc
  • Submitted: 2002-09-20
  • Updated: 2003-01-07
  • Resolved: 2002-11-01
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other Other Other
1.4.0_04 04Fixed 1.4.1_02Fixed 1.4.2Fixed
Related Reports
Duplicate :  
Relates :  
Description
The 1.4.2 server VM throws a bad ArrayIndexOutOfBoundsException in the copying loop (similar to the previously fixed problem - 4629512 ). 

The test case below exits because of the ArrayIndexOutOfBoundsException inside the copying loop on 32 bit solaris in the server mode. Same test case runs correctly (without exiting) with the client compiler. The problem didn't exist in 1.3.1 and 1.2.2

public class ReadTest {

        private Buffer _current;
        private final int BYTE_SIZE = 1;
        private int _offsetInChunk;

        public static void main(String[] args) {
                final String _data = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
                Buffer in = new Buffer(_data);
                ReadTest test = new ReadTest(in);
                char[] value = new char[10];
                int offset = 0;
                int length = 10;
                while (true) {
                        for(int i=0; i<6; i++) {
                                test.testMethod(value, offset, length);
                                System.out.println(value);
                        }
                        Buffer in2 = new Buffer(_data);
                        in.next = in2;
                        in = in2;
                }
        }

        private ReadTest(Buffer buffer) {
                _current = buffer;
        }

        private void testMethod(char[] value, int offset, int length) {

                if((value == null) || (value.length-offset < length)) {
                        System.out.println("### ERROR1 ###");
                        return;
                }

                int inLengthInBytes = length * BYTE_SIZE;
                int numBytesToCopy = 0;

                while(inLengthInBytes > 0) {
                        if (_offsetInChunk >= _current.dataEndOffset) {
                                _offsetInChunk -= _current.dataEndOffset;
                                if(_current.next == null) {
                                        System.out.println("### ERROR2 ###");
                                        return;
                                }
                                _current = _current.next;
                                _offsetInChunk += _current.dataStartOffset;
                        }

                        numBytesToCopy = _current.dataEndOffset - _offsetInChunk;
                        if (inLengthInBytes < numBytesToCopy) {
                                numBytesToCopy = inLengthInBytes;
                        }

                        int i = 0, max = 0;
                        try {
                                for(i = offset, max = numBytesToCopy; max > 0; i++, max -= BYTE_SIZE) {
                                        value[i] = (char)(_current.data[_offsetInChunk++] & 0xff);
                                        if (value[i] == 0) {
                                                System.out.println("### ERROR3 ###");
                                                return;
                                        }
                                }
                        } catch(ArrayIndexOutOfBoundsException aioobe) {
                                System.out.println("+++++++++++++++++++++++++++++");
                                System.out.println(" value          = " + new String(value));
                                System.out.println(" value's length = " + value.length);
                                System.out.println(" value's i      = " + i);
                                System.out.println(" max            = " + max);
                                System.out.println(" numBytesToCopy = " + numBytesToCopy);
                                System.out.println(" BYTE_SIZE      = " + BYTE_SIZE);
                                System.out.println(" offset         = " + offset);
                                System.out.println("+++++++++++++++++++++++++++++");
                                System.exit(1);
                        }
                        inLengthInBytes -= numBytesToCopy;
                        offset += numBytesToCopy / BYTE_SIZE;
                }
        }

}

class Buffer {

        public byte[] data;
        public int dataStartOffset;
        public int dataEndOffset;
        public Buffer next;

        public Buffer(String _data) {
                int chunkSize = dataEndOffset = _data.length();
                data = _data.getBytes();
        }
}

Output:

bash-2.00$ /java/re/jdk/1.4.2/promoted/latest/binaries/solaris-sparc/bin/java_g -XX:CompileOnly=ReadTest.testMethod -server ReadTest
VM option 'CompileOnly=ReadTest.testMethod'
ABCDEFGHIJ
KLMNOPQRST
..........
+++++++++++++++++++++++++++++
 value          = 34567890AB
 value's length = 10
 value's i      = 10
 max            = 0
 numBytesToCopy = 2
 BYTE_SIZE      = 1
 offset         = 8
+++++++++++++++++++++++++++++

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: 1.4.0_04 1.4.1_02 mantis FIXED IN: 1.4.0_04 1.4.1_02 mantis INTEGRATED IN: 1.4.0_04 1.4.1_02 mantis
14-06-2004

EVALUATION ###@###.### 2002-09-20 Reproduces with current c2_baseline. ----- ----- I simplified the test file somewhat. Reproduces with -Xbatch -Xcomp -XX:+PrintOpto -XX:CompileOnly=.testMethod -XX:LoopUnrollLimit=80 ReadTest on both sparc & intel. ###@###.### 2002-09-23 Testcase didn't failed with option "-XX:LoopUnrollLimit=" set to 45. I tested with 1.4.1 and 1.4.2 on Solaris and with 1.4.0-rc on Intel. If I increase the LoopUnrollLimit testcase starts failing again. ###@###.### 2002-09-27 OBOB in the Range Check Elimination code; negative stride*scale handling case (which triggers in a variety of loop shapes, not just count-down loops or count-up loops with negative scale). In the long comments starting around line 784 loopTransform.cpp, there is an assumption: ASSUME: (I % stride_con) == 0. This assumption is almost but not quite right: ((I-I_initial) % stride_con) == 0. I cut short the derivation of the min/max equations and end up with a tiny bit more code run and compile-time and approximately the same code generated but with the OBOB fixed. ###@###.### 2002-10-03 Fix backported to 1.4.1_02. Bugtraq is not allowing me to save with Resp Eng as "cliffc", so changing it to default. ###@###.### 2002-12-11
03-10-2002

WORK AROUND There was no failure when I ran the testcase with development flag "-XX:-RangeCheckElimination" option in 1.4.0. ###@###.### 2002-09-24
24-09-2002