JDK-6612412 : FloatBuffer returns incorrect results when used with the Java 6 HotSpot ServerVM
  • Type: Enhancement
  • Component: hotspot
  • Sub-Component: compiler
  • Affected Version: 6
  • Priority: P5
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2007-10-03
  • Updated: 2011-02-16
  • Resolved: 2007-10-03
Related Reports
Duplicate :  
Description
FULL PRODUCT VERSION :
Linux
java version "1.6.0_02"
Java(TM) SE Runtime Environment (build 1.6.0_02-b05)
Java HotSpot(TM) Server VM (build 1.6.0_02-b05, mixed mode)

WIndows XP (32-bit)
java version "1.6.0_02"
Java(TM) SE Runtime Environment (build 1.6.0_02-b06)
Java HotSpot(TM) Client VM (build 1.6.0_02-b06, mixed mode, sharing)

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 :
NOTE: Same bug as reported in http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6550579
  Bug 6550579 shows a status of closed, fixed, but as of the latest Java6 updated, the bug is still present. Request to have this fix backported to 6.0.

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.

EXPECTED VERSUS ACTUAL BEHAVIOR :
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-b06
Java name Java HotSpot(TM) Client VM

java -server FloatBufferTest
Error count for the current loop in comparing FloatBuffer to float src array 24668
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: 1
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-b06
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 ----------

Comments
EVALUATION Fixed in 6u4: hsdev-5% /java/re/jdk/1.6.0_04/latest/binaries/solaris-i586/bin/java -server 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 10.0-b17 Java name Java HotSpot(TM) Server VM
03-10-2007