changeset 57674:d9af3d39f4d3

8230665: (bf spec) ByteBuffer::alignmentOffset spec misleading when address is misaligned Reviewed-by: alanb, darcy, psandoz
author bpb
date Tue, 14 Jan 2020 11:06:00 -0800
parents df7db8638f96
children 8b9577d77bba
files src/java.base/share/classes/java/nio/X-Buffer.java.template test/jdk/java/nio/Buffer/Basic-X.java.template test/jdk/java/nio/Buffer/BasicByte.java
diffstat 3 files changed, 112 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/src/java.base/share/classes/java/nio/X-Buffer.java.template	Tue Jan 14 10:25:22 2020 -0800
+++ b/src/java.base/share/classes/java/nio/X-Buffer.java.template	Tue Jan 14 11:06:00 2020 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1869,14 +1869,26 @@
 
     /**
      * Returns the memory address, pointing to the byte at the given index,
-     * modulus the given unit size.
+     * modulo the given unit size.
      *
-     * <p> A return value greater than zero indicates the address of the byte at
-     * the index is misaligned for the unit size, and the value's quantity
-     * indicates how much the index should be rounded up or down to locate a
-     * byte at an aligned address.  Otherwise, a value of {@code 0} indicates
-     * that the address of the byte at the index is aligned for the unit size.
-     *
+     * <p> The return value is non-negative, with {@code 0} indicating that the
+     * address of the byte at the index is aligned for the unit size, and a
+     * positive value that the address is misaligned for the unit size.  If the
+     * address of the byte at the index is misaligned, the return value
+     * represents how much the index should be adjusted to locate a byte at an
+     * aligned address.  Specifically, the index should either be decremented by
+     * the return value, or incremented by the unit size minus the return value.
+     * Therefore given
+     * <blockquote><pre>
+     * int value = alignmentOffset(index, unitSize)</pre></blockquote>
+     * then the identities
+     * <blockquote><pre>
+     * alignmentOffset(index - value, unitSize) == 0</pre></blockquote>
+     * and
+     * <blockquote><pre>
+     * alignmentOffset(index + (unitSize - value), unitSize) == 0</pre></blockquote>
+     * must hold.
+     * 
      * @apiNote
      * This method may be utilized to determine if unit size bytes from an
      * index can be accessed atomically, if supported by the native platform.
@@ -1892,7 +1904,7 @@
      * @param  unitSize
      *         The unit size in bytes, must be a power of {@code 2}
      *
-     * @return  The indexed byte's memory address modulus the unit size
+     * @return  The indexed byte's memory address modulo the unit size
      *
      * @throws IllegalArgumentException
      *         If the index is negative or the unit size is not a power of
@@ -1918,7 +1930,7 @@
         if (unitSize > 8 && !isDirect())
             throw new UnsupportedOperationException("Unit size unsupported for non-direct buffers: " + unitSize);
 
-        return (int) ((address + index) % unitSize);
+        return (int) ((address + index) & (unitSize - 1));
     }
 
     /**
--- a/test/jdk/java/nio/Buffer/Basic-X.java.template	Tue Jan 14 10:25:22 2020 -0800
+++ b/test/jdk/java/nio/Buffer/Basic-X.java.template	Tue Jan 14 11:06:00 2020 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,7 +30,16 @@
 
 #warn This file is preprocessed before being compiled
 
+#if[byte]
+import java.io.IOException;
+import java.io.UncheckedIOException;
+#end[byte]
 import java.nio.*;
+#if[byte]
+import java.nio.channels.FileChannel;
+import java.nio.file.Files;
+import java.nio.file.Path;
+#end[byte]
 
 
 public class Basic$Type$
@@ -469,6 +478,41 @@
                 }
             }
         }
+
+        // mapped buffers
+        try {
+            for (MappedByteBuffer bb : mappedBuffers()) {
+                try {
+                    int offset = bb.alignmentOffset(1, 4);
+                    ck(bb, offset >= 0);
+                } catch (UnsupportedOperationException e) {
+                    System.out.println("Not applicable, UOE thrown: ");
+                }
+            }
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+
+    private static MappedByteBuffer[] mappedBuffers() throws IOException {
+        return new MappedByteBuffer[]{
+                createMappedBuffer(new byte[]{0, 1, 2, 3}),
+                createMappedBuffer(new byte[]{0, 1, 2, -3,
+                    45, 6, 7, 78, 3, -7, 6, 7, -128, 127}),
+        };
+    }
+
+    private static MappedByteBuffer createMappedBuffer(byte[] contents)
+        throws IOException {
+        Path tempFile = Files.createTempFile("mbb", null);
+        tempFile.toFile().deleteOnExit();
+        Files.write(tempFile, contents);
+        try (FileChannel fc = FileChannel.open(tempFile)) {
+            MappedByteBuffer map =
+                fc.map(FileChannel.MapMode.READ_ONLY, 0, contents.length);
+            map.load();
+            return map;
+        }
     }
 #end[byte]
 
--- a/test/jdk/java/nio/Buffer/BasicByte.java	Tue Jan 14 10:25:22 2020 -0800
+++ b/test/jdk/java/nio/Buffer/BasicByte.java	Tue Jan 14 11:06:00 2020 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,8 +30,17 @@
 
 // -- This file was mechanically generated: Do not edit! -- //
 
+
+import java.io.IOException;
+import java.io.UncheckedIOException;
+
 import java.nio.*;
 
+import java.nio.channels.FileChannel;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+
 
 public class BasicByte
     extends Basic
@@ -469,6 +478,41 @@
                 }
             }
         }
+
+        // mapped buffers
+        try {
+            for (MappedByteBuffer bb : mappedBuffers()) {
+                try {
+                    int offset = bb.alignmentOffset(1, 4);
+                    ck(bb, offset >= 0);
+                } catch (UnsupportedOperationException e) {
+                    System.out.println("Not applicable, UOE thrown: ");
+                }
+            }
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+
+    private static MappedByteBuffer[] mappedBuffers() throws IOException {
+        return new MappedByteBuffer[]{
+                createMappedBuffer(new byte[]{0, 1, 2, 3}),
+                createMappedBuffer(new byte[]{0, 1, 2, -3,
+                    45, 6, 7, 78, 3, -7, 6, 7, -128, 127}),
+        };
+    }
+
+    private static MappedByteBuffer createMappedBuffer(byte[] contents)
+        throws IOException {
+        Path tempFile = Files.createTempFile("mbb", null);
+        tempFile.toFile().deleteOnExit();
+        Files.write(tempFile, contents);
+        try (FileChannel fc = FileChannel.open(tempFile)) {
+            MappedByteBuffer map =
+                fc.map(FileChannel.MapMode.READ_ONLY, 0, contents.length);
+            map.load();
+            return map;
+        }
     }