Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6550579

FloatBuffer returns incorrect results when used with the Java 6 HotSpot ServerVM

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: P3
    • Resolution: Fixed
    • Affects Version/s: 6
    • Fix Version/s: hs10
    • Component/s: hotspot
    • Labels:
    • Subcomponent:
    • Introduced In Build:
      b19
    • Introduced In Version:
      6
    • Resolved In Build:
      b13
    • CPU:
      x86
    • OS:
      windows_xp

      Backports

        Description

        FULL PRODUCT VERSION :
        java version "1.6.0_01"
        Java(TM) SE Runtime Environment (build 1.6.0_01-b06)
        Java HotSpot(TM) Server VM (build 1.6.0_01-b06, mixed mode)

        FULL OS VERSION :
        WindowsXP (SP2+patches)
        Linux 2.6.9-22.ELsmp x86_64
        Linux 2.6.9-22.ELsmp i686 i386

        A DESCRIPTION OF THE PROBLEM :
        When using a java.nio.FloatBuffer in a loop, the values placed into the FloatBuffer via the put( float[], int, int) method are not always equal to the values of the source float[] data when the program is executed using the Hotspot Server VM (-server option).

        Note that the problem appears to only be present when the jvm is executed with the -server option. If -client is used, the FloatBuffer values are correct.

        Note that sometimes the data in the FloatBuffer is correct. It's the use of a FloatBuffer in a loop that appears to be part of the problem (at least as discovered and tested).

        This problem appears to be new to Java 6 and is not present in the Java 1.4 or Java 5 vms that I tested.

        THE PROBLEM WAS REPRODUCIBLE WITH -Xint FLAG: Did not try

        THE PROBLEM WAS REPRODUCIBLE WITH -server FLAG: Yes

        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        1. Create a loop that executes more than 1 time
        2. Copy an array for floats into a java.nio.FloatBuffer using the put(float[], int, int) method. Ref http://java.sun.com/javase/6/docs/api/java/nio/FloatBuffer.html#put(float[],%20int,%20int)
        3. Compare values of the source float array to those values in the FloatBuffer
        4. Execute with the '-server' jvm option (e.g. java -server FloatBufferTest)

        EXPECTED VERSUS ACTUAL BEHAVIOR :
        When tested in prior jvms and in the Java 6 jvm using the '-client' option, the source float array and the values copied into the FloatBuffer are the same (as they should be). When tested in the Java 6 jvm using the '-server' option, the source float array and the values copied into the FloatBuffer are not always the same when the FloatBuffer is being used inside of a loop.

        ACTUAL -

        java FloatBufferTest
        0 loops experienced errors. Total FloatBuffer loops executed 1000
        0 loops experienced errors. Total DoubleBuffer loops executed 1000
        0 IntBuffer loops experienced errors. Total IntBuffer loops executed 1000
        Java version 1.6.0_02-ea-b02
        Java name Java HotSpot(TM) Client VM

        java -server FloatBufferTest
        Error count for the current loop in comparing FloatBuffer to float src array 17618
        Error count for the current loop in comparing FloatBuffer to float src array 24386
        2 loops experienced errors. Total FloatBuffer loops executed 1000
        First FloatBuffer loop to error: 0
        0 loops experienced errors. Total DoubleBuffer loops executed 1000
        0 IntBuffer loops experienced errors. Total IntBuffer loops executed 1000
        Java version 1.6.0_02-ea-b02
        Java name Java HotSpot(TM) Server VM

        REPRODUCIBILITY :
        This bug can be reproduced always.



        ---------- BEGIN SOURCE ----------
        import java.nio.ByteBuffer;
        import java.nio.DoubleBuffer;
        import java.nio.FloatBuffer;
        import java.nio.IntBuffer;
        import java.util.Random;

        /**
         * The FloatBufferTest demonstrates an error in the FloatBuffer when executed
         * with the Java 6 jvm with the jvm arg '-server'. If the Java 6 jvm is executed
         * in client mode, then there is no error.
         *
         * Also worth noting is that the Java 1.4 and Java 5 jvms execute the code
         * without any errors for both jvm args '-server' and '-client'.
         *
         * To see the errors execute the code below using the Java 6 jvm with '-server'
         * specified.
         *
         * example: java -server FloatBufferTest
         *
         * Execute the same code using the same Java 6 jvm without the '-server' option
         * and no errors are produced.
         *
         * example: java FloatBufferTest or java -client FloatBufferTest
         *
         * Java version: Java version 1.6.0_01-b06
         *
         * Misc: The IntBuffer and DoubleBuffer are also tested in the same manner that
         * the FloatBuffer is tested and no errors have been seen using the same scenario.
         * Perhaps execution order of the methods may affect the outcome (not tested).
         */
        public class FloatBufferTest {


        private static int NUM_LOOPS = 1000;

        //change to true to dump error values to console
        //note that doing so may affect results
        private static boolean DUMP_ERROR_VALUES = false;

        public static void main(String[] args) {
        long seed = 8675309;
        int dlength = 50000; // 50000 entries

        FloatBufferTest.testFloatBuffer(seed, dlength);
        //test DoubleBuffer in the same manner
        FloatBufferTest.testDoubleBuffer(seed, dlength);
        //test IntBuffer in the same manner
        FloatBufferTest.testIntBuffer(seed, dlength);

        //dump some jvm info
        String jvmversion = System.getProperty("java.vm.version");
        String jvmname = System.getProperty("java.vm.name");
        System.err.println("Java version " + jvmversion);
        System.err.println("Java name " + jvmname);

        }

        /**
        * Test the FloatBuffer
        * @param pSeed the seed value
        * @param pLength the number of data values
        */
        protected static void testFloatBuffer(long pSeed, int pLength) {

        int blength = 4; // 4 btyes
        float[] floats = new float[pLength];

        Random r = new Random(pSeed);
        //populate src float array
        for (int i = 0; i < pLength; i++) {
        floats[i] = r.nextFloat();
        }


        int loopErrorCount = 0;
        int firstLoopToErr = -1;





        for (int ii = 0; ii <= NUM_LOOPS; ii++) {

        ByteBuffer destbb = ByteBuffer.allocate(pLength * blength);
        FloatBuffer fb = destbb.asFloatBuffer();
        fb.put(floats, 0, pLength);

        int errorCount = 0;
        //compare source float values to those copied into the FloatBuffer
        for (int i = 0; i < floats.length; i++) {
        float fbfvalue = fb.get(i);
        float srcvalue = floats[i];
        //check for mismatching values
        if (fbfvalue != srcvalue) {
        errorCount++;

        if (DUMP_ERROR_VALUES) {
        System.err.println("*** Data values not equal error");
        System.err.println(i + " (array index) Expected " + srcvalue
        + ", got " + fbfvalue);
        }

        }
        } //end i

        //check if there where any errors in loop execution
        if (errorCount > 0) {
        //track the first loop to error
        if (firstLoopToErr == -1) {
        firstLoopToErr = ii;
        }
        loopErrorCount++;
        System.err
        .println("Error count for the current loop in comparing FloatBuffer to float src array "
        + errorCount);
        }


        }// end ii

        System.err.println(loopErrorCount + " loops experienced errors. Total FloatBuffer loops executed " + NUM_LOOPS);
        if (loopErrorCount > 0) {
        System.err.println("First FloatBuffer loop to error: " + firstLoopToErr);
        }

        }

        /**
        * Test the DoubleBuffer
        * @param pSeed the seed value
        * @param pLength the number of data values
        */
        protected static void testDoubleBuffer(long pSeed, int pLength) {

        int blength = 8; // 8 btyes
        double[] src = new double[pLength];

        Random r = new Random(pSeed);
        //populate src array
        for (int i = 0; i < pLength; i++) {
        src[i] = r.nextDouble();
        }


        int loopErrorCount = 0;
        int firstLoopToErr = -1;





        for (int ii = 0; ii <= NUM_LOOPS; ii++) {

        ByteBuffer destbb = ByteBuffer.allocate(pLength * blength);
        DoubleBuffer fb = destbb.asDoubleBuffer();
        fb.put(src, 0, pLength);

        int errorCount = 0;
        //compare source float values to those copied into the DoubleBuffer
        for (int i = 0; i < src.length; i++) {
        double fbfvalue = fb.get(i);
        double srcvalue = src[i];
        //check for mismatching values
        if (fbfvalue != srcvalue) {
        errorCount++;

        if (DUMP_ERROR_VALUES) {
        System.err.println("*** Data values not equal error");
        System.err.println(i + " (array index) Expected " + srcvalue
        + ", got " + fbfvalue);
        }

        }
        } //end i

        //check if there where any errors in loop execution
        if (errorCount > 0) {
        //track the first loop to error
        if (firstLoopToErr == -1) {
        firstLoopToErr = ii;
        }
        loopErrorCount++;
        System.err
        .println("Error count for the current loop in comparing DoubleBuffer to double src array "
        + errorCount);
        }


        }// end ii

        System.err.println(loopErrorCount + " loops experienced errors. Total DoubleBuffer loops executed " + NUM_LOOPS);
        if (loopErrorCount > 0) {
        System.err.println("First DoubleBuffer loop to error: " + firstLoopToErr);
        }

        }

        /**
        * Test the IntBuffer
        * @param pSeed the seed value
        * @param pLength the number of data values
        */
        protected static void testIntBuffer(long pSeed, int pLength) {

        int blength = 4; // 4 btyes
        int[] src = new int[pLength];

        Random r = new Random(pSeed);
        //populate src array
        for (int i = 0; i < pLength; i++) {
        src[i] = r.nextInt();
        }


        int loopErrorCount = 0;
        int firstLoopToErr = -1;





        for (int ii = 0; ii <= NUM_LOOPS; ii++) {

        ByteBuffer destbb = ByteBuffer.allocate(pLength * blength);
        IntBuffer fb = destbb.asIntBuffer();
        fb.put(src, 0, pLength);

        int errorCount = 0;
        //compare source float values to those copied into the IntBuffer
        for (int i = 0; i < src.length; i++) {
        int fbfvalue = fb.get(i);
        int srcvalue = src[i];
        //check for mismatching values
        if (fbfvalue != srcvalue) {
        errorCount++;

        if (DUMP_ERROR_VALUES) {
        System.err.println("*** Data values not equal error");
        System.err.println(i + " (array index) Expected " + srcvalue
        + ", got " + fbfvalue);
        }

        }
        } //end i

        //check if there where any errors in loop execution
        if (errorCount > 0) {
        //track the first loop to error
        if (firstLoopToErr == -1) {
        firstLoopToErr = ii;
        }
        loopErrorCount++;
        System.err
        .println("Error count for the current loop in comparing IntBuffer to double src array "
        + errorCount);
        }


        }// end ii

        System.err.println(loopErrorCount + " IntBuffer loops experienced errors. Total IntBuffer loops executed " + NUM_LOOPS);
        if (loopErrorCount > 0) {
        System.err.println("First IntBuffer loop to error: " + firstLoopToErr);
        }

        }


        }
        ---------- END SOURCE ----------

        CUSTOMER SUBMITTED WORKAROUND :
        Preliminary testing shows the usage of put (int index, float value) (Ref http://java.sun.com/javase/6/docs/api/java/nio/FloatBuffer.html#put(int,%20float) )
        to be a possible workaround, although it has not been tested on all platforms

          Attachments

            Issue Links

              Activity

                People

                • Assignee:
                  kvn Vladimir Kozlov
                  Reporter:
                  ndcosta Nelson Dcosta (Inactive)
                • Votes:
                  0 Vote for this issue
                  Watchers:
                  1 Start watching this issue

                  Dates

                  • Created:
                    Updated:
                    Resolved:
                    Imported:
                    Indexed: