# HG changeset patch
# User redestad
# Date 1459712436 -7200
# Sun Apr 03 21:40:36 2016 +0200
# Node ID 2e7e22837c8552f0253f25fd34df37f080e8120c
# Parent 68f8be44b6a6b33dfa841ec671c0ba6e4056b372
8153334: Replace BufferedInputStreams use of AtomicReferenceFieldUpdater with Unsafe
Reviewed-by: alanb, forax
diff --git a/src/java.base/share/classes/java/io/BufferedInputStream.java b/src/java.base/share/classes/java/io/BufferedInputStream.java
--- a/src/java.base/share/classes/java/io/BufferedInputStream.java
+++ b/src/java.base/share/classes/java/io/BufferedInputStream.java
@@ -24,7 +24,8 @@
*/
package java.io;
-import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
+
+import jdk.internal.misc.Unsafe;
/**
* A BufferedInputStream
adds
@@ -68,15 +69,21 @@
protected volatile byte buf[];
/**
- * Atomic updater to provide compareAndSet for buf. This is
- * necessary because closes can be asynchronous. We use nullness
+ * Get Unsafe and offset of buf to provide compareAndSet functionality.
+ * 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 bufUpdater =
- AtomicReferenceFieldUpdater.newUpdater
- (BufferedInputStream.class, byte[].class, "buf");
+ private static final Unsafe UNSAFE = Unsafe.getUnsafe();
+ private static final long BUF_OFFSET;
+ static {
+ try {
+ BUF_OFFSET = UNSAFE.objectFieldOffset(
+ BufferedInputStream.class.getDeclaredField("buf"));
+ } catch (ReflectiveOperationException e) {
+ throw new Error(e);
+ }
+ }
/**
* The index one greater than the index of the last valid byte in
@@ -212,9 +219,9 @@
*/
private void fill() throws IOException {
byte[] buffer = getBufIfOpen();
- if (markpos < 0)
+ if (markpos < 0) {
pos = 0; /* no mark: throw away the buffer */
- else if (pos >= buffer.length) /* no room left in buffer */
+ } else if (pos >= buffer.length) { /* no room left in buffer */
if (markpos > 0) { /* can throw away early part of the buffer */
int sz = pos - markpos;
System.arraycopy(buffer, markpos, buffer, 0, sz);
@@ -232,7 +239,8 @@
nsz = marklimit;
byte nbuf[] = new byte[nsz];
System.arraycopy(buffer, 0, nbuf, 0, pos);
- if (!bufUpdater.compareAndSet(this, buffer, nbuf)) {
+ if (!UNSAFE.compareAndSwapObject(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.
@@ -242,6 +250,7 @@
}
buffer = nbuf;
}
+ }
count = pos;
int n = getInIfOpen().read(buffer, pos, buffer.length - pos);
if (n > 0)
@@ -476,7 +485,7 @@
public void close() throws IOException {
byte[] buffer;
while ( (buffer = buf) != null) {
- if (bufUpdater.compareAndSet(this, buffer, null)) {
+ if (UNSAFE.compareAndSwapObject(this, BUF_OFFSET, buffer, null)) {
InputStream input = in;
in = null;
if (input != null)