Duplicate :
|
Name: nt126004 Date: 04/29/2003 FULL PRODUCT VERSION : java version "1.4.1_01" Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1_01-b01) Java HotSpot(TM) Client VM (build 1.4.1_01-b01, mixed mode FULL OPERATING SYSTEM VERSION : glibc-2.2.4-21 kernel 2.4.10-4GB distribution SuSE-release ADDITIONAL OPERATING SYSTEMS : Red Hat Linux A DESCRIPTION OF THE PROBLEM : When I use the getDouble() method to interpret part of a ByteBuffer, using allocateDirect, as a double, the results I get do not agree with the interpretation of the same set of bytes from the ByteBuffer if I use a DataInputStream with a ByteArrayInputStream. This is not for every double value that I have interpreted, only some of them. Moreover, the double with the different value that is interpreted by using DataInputStream and ByteArrayInputStream matches the values returned by getDouble() on other operating systems that I have tried this on, such as Windows 2000 and Solaris 8. The problem only occurs on Linux. I have tried this on Suse Linux and Red Hat Linux and both have this problem. Also, this problem does not occur on Linux when the ByteBuffer is allocated using allocate(), only when using allocateDirect(). STEPS TO FOLLOW TO REPRODUCE THE PROBLEM : I've attached some code I used to read in some binary data that exhibits these problems. I used the same binary file when I ran this code twice, once using getDouble() and once using getMyDouble. When I comment in the use of the getMyDouble method (uses ByteArrayInputStream and DataInputStream to get a double value), one of the values that prints is not the same as when I use the getDouble() method on the ByteBuffer. The code includes a comment at the top with the uuencode for the binary data that I used for the test case. Cut and paste from the comment from begin... to end, save as a file and uudecode it to create the binary data for the program. Pass the file name from the uudecode as a command line argument to the test case program. EXPECTED VERSUS ACTUAL BEHAVIOR : Note that the only item that is different is the value of L2RawRange: Here's the output of the program when I use getDouble: Before L1CarrierPhase= 65,1,77,36,-50,-64,0,0, Before L1RawRange= 63,-77,-73,-107,-122,-13,123,50, Before L2CarrierPhase= 64,-6,25,96,93,0,0,0, Before L2RawRange= 63,-77,-73,-106,33,125,-9,-1, After L1CarrierPhase= 65,1,77,36,-50,-64,0,0, After L1RawRange= 63,-77,-73,-107,-122,-13,123,50, After L2CarrierPhase= 64,-6,25,96,93,0,0,0, After L2RawRange= 63,-77,-73,-106,33,125,-9,-1, L1CarrierPhase=141732.60095214844 L1RawRange=0.07702002091126017 L2CarrierPhase=106902.02270507812 L2RawRange=0.07702005689316137 Here's the output of the program when I use getMyDouble (ByteArrayInputStream and DataInputStream). These values agree with result from getDouble() on Solaris and Windows: Before L1CarrierPhase= 65,1,77,36,-50,-64,0,0, Before L1RawRange= 63,-77,-73,-107,-122,-13,123,50, Before L2CarrierPhase= 64,-6,25,96,93,0,0,0, Before L2RawRange= 63,-77,-73,-106,33,125,-9,-1, After L1CarrierPhase= 65,1,77,36,-50,-64,0,0, After L1RawRange= 63,-77,-73,-107,-122,-13,123,50, After L2CarrierPhase= 64,-6,25,96,93,0,0,0, After L2RawRange= 63,-77,-73,-106,33,125,-9,-1, L1CarrierPhase=141732.60095214844 L1RawRange=0.07702002091126017 L2CarrierPhase=106902.02270507812 L2RawRange=0.07702005689313295 REPRODUCIBILITY : This bug can be reproduced always. ---------- BEGIN SOURCE ---------- import java.io.*; import java.nio.*; import java.nio.channels.*; public class NIORead { /* Binary input data as uuencoded data: begin 644 NIObinary.dbl M00%-),[````_L[>5AO-[,D#Z&6!=````/[.WEB%]]_\-"D$">8]ON```/[.W M^^1^]/]`^^V.]V```#^SM_Q^'>B)#0I!;E(&PL0``#^R)GA7Q8<I06>7WRL@ ,H``_LB9XTO7V?PT* ` end */ public static void main(String [] args) throws IOException { ByteBuffer buff = ByteBuffer.allocateDirect(150); FileInputStream fis = new FileInputStream(args[0]); FileChannel fcin = fis.getChannel(); buff.limit(32); long numBytes = fcin.read(buff); printBytes("Before L1CarrierPhase",buff, 0, 8); printBytes("Before L1RawRange",buff, 8, 8); printBytes("Before L2CarrierPhase",buff, 16, 8); printBytes("Before L2RawRange",buff, 24, 8); double L1CarrierPhase = buff.getDouble(0); double L1RawRange = buff.getDouble(8); double L2CarrierPhase = buff.getDouble(16); double L2RawRange = buff.getDouble(24); /* double L1CarrierPhase = myGetDouble(buff,0); double L1RawRange = myGetDouble(buff,8); double L2CarrierPhase = myGetDouble(buff,16); double L2RawRange = myGetDouble(buff,24); */ printBytes("After L1CarrierPhase",buff, 0, 8); printBytes("After L1RawRange",buff, 8, 8); printBytes("After L2CarrierPhase",buff, 16, 8); printBytes("After L2RawRange",buff, 24, 8); System.out.println ("L1CarrierPhase=" + L1CarrierPhase); System.out.println ("L1RawRange=" + L1RawRange); System.out.println ("L2CarrierPhase=" + L2CarrierPhase); System.out.println ("L2RawRange=" + L2RawRange); fcin.close(); fis.close(); } public static double myGetDouble(ByteBuffer buff, int offset) throws java.io.IOException { byte [] dBytes = new byte[8]; buff.position(offset); buff.get(dBytes); ByteArrayInputStream bais = new ByteArrayInputStream(dBytes); DataInputStream dis = new DataInputStream( new ByteArrayInputStream(dBytes)); double dValue = dis.readDouble(); dis.close(); return dValue; } public static void printBytes(String label, ByteBuffer buff, int start, int length) { byte [] dBytes = new byte[length]; System.out.println(label + "="); int index = start; for (int i=0;i<dBytes.length;i++) { dBytes[i] = buff.get(index); System.out.print(Byte.toString(dBytes[i]) + ","); index++; } System.out.println(""); } } ---------- END SOURCE ---------- CUSTOMER WORKAROUND : Use a ByteArrayInputStream and a DataInputStream to interpret doubles in ByteBuffers or use allocate() instead of allocateDirect() on Linux. (Review ID: 179870) ======================================================================