< prev index next >

src/java.base/share/classes/java/io/BufferedInputStream.java

Print this page
rev 17627 : 8185362: Replace use of AtomicReferenceFieldUpdater from BufferedInputStream with Unsafe
Reviewed-by: shade

@@ -22,11 +22,12 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
 
 package java.io;
-import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
+
+import jdk.internal.misc.Unsafe;
 
 /**
  * A <code>BufferedInputStream</code> adds
  * functionality to another input stream-namely,
  * the ability to buffer the input and to

@@ -58,27 +59,21 @@
      * Attempts to allocate larger arrays may result in
      * OutOfMemoryError: Requested array size exceeds VM limit
      */
     private static int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8;
 
+    private static final Unsafe U = Unsafe.getUnsafe();
+
+    private static final long BUF_OFFSET
+            = U.objectFieldOffset(BufferedInputStream.class, "buf");
+
     /**
      * The internal buffer array where the data is stored. When necessary,
      * it may be replaced by another array of
      * a different size.
      */
-    protected volatile byte buf[];
-
-    /**
-     * Atomic updater to provide compareAndSet for buf. This is
-     * necessary because closes can be asynchronous. We use nullness
-     * of buf[] as primary indicator that this stream is closed. (The
-     * "in" field is also nulled out on close.)
-     */
-    private static final
-        AtomicReferenceFieldUpdater<BufferedInputStream, byte[]> bufUpdater =
-        AtomicReferenceFieldUpdater.newUpdater
-        (BufferedInputStream.class,  byte[].class, "buf");
+    protected volatile byte[] buf;
 
     /**
      * The index one greater than the index of the last valid byte in
      * the buffer.
      * This value is always

@@ -230,11 +225,11 @@
                         pos * 2 : MAX_BUFFER_SIZE;
                 if (nsz > marklimit)
                     nsz = marklimit;
                 byte nbuf[] = new byte[nsz];
                 System.arraycopy(buffer, 0, nbuf, 0, pos);
-                if (!bufUpdater.compareAndSet(this, buffer, nbuf)) {
+                if (!U.compareAndSetObject(this, BUF_OFFSET, buffer, nbuf)) {
                     // Can't replace buf if there was an async close.
                     // Note: This would need to be changed if fill()
                     // is ever made accessible to multiple threads.
                     // But for now, the only way CAS can fail is via close.
                     // assert buf == null;

@@ -474,11 +469,11 @@
      * @exception  IOException  if an I/O error occurs.
      */
     public void close() throws IOException {
         byte[] buffer;
         while ( (buffer = buf) != null) {
-            if (bufUpdater.compareAndSet(this, buffer, null)) {
+            if (U.compareAndSetObject(this, BUF_OFFSET, buffer, null)) {
                 InputStream input = in;
                 in = null;
                 if (input != null)
                     input.close();
                 return;
< prev index next >