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

(bf) ByteBuffer.getDouble() does not always return correct value (linux)

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P4 P4
    • None
    • 1.4.1
    • core-libs
    • x86
    • linux



      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)
      ======================================================================

            mr Mark Reinhold
            nthompsosunw Nathanael Thompson (Inactive)
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: