http-client-impl: drop usage of ByteBufferReference temporarily. Using it properly requires changing FlowTube to work with List<BBR> or BBR[] instead of List<BB>. May be added back later if there is a performance gain. http-client-branch
authordfuchs
Mon, 13 Nov 2017 14:56:09 +0000
branchhttp-client-branch
changeset 55806 e8bc8370f528
parent 55805 371ed971281e
child 55807 2337a59be92a
http-client-impl: drop usage of ByteBufferReference temporarily. Using it properly requires changing FlowTube to work with List<BBR> or BBR[] instead of List<BB>. May be added back later if there is a performance gain.
src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/ConnectionPool.java
src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/Http1AsyncReceiver.java
src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/Http2Connection.java
src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/Stream.java
src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/internal/frame/ContinuationFrame.java
src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/internal/frame/DataFrame.java
src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/internal/frame/FramesDecoder.java
src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/internal/frame/FramesEncoder.java
src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/internal/frame/HeaderFrame.java
src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/internal/frame/HeadersFrame.java
src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/internal/frame/PushPromiseFrame.java
test/jdk/java/net/httpclient/http2/server/BodyInputStream.java
test/jdk/java/net/httpclient/http2/server/BodyOutputStream.java
test/jdk/java/net/httpclient/http2/server/Http2TestServerConnection.java
test/jdk/java/net/httpclient/whitebox/jdk.incubator.httpclient/jdk/incubator/http/ConnectionPoolTest.java
--- a/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/ConnectionPool.java	Mon Nov 13 16:13:11 2017 +0300
+++ b/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/ConnectionPool.java	Mon Nov 13 14:56:09 2017 +0000
@@ -104,11 +104,6 @@
         }
     }
 
-    /* Exposed for testing */
-    ConnectionPool() {
-        this("ConnectionPool(?)");
-    }
-
     ConnectionPool(long clientId) {
         this("ConnectionPool("+clientId+")");
     }
--- a/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/Http1AsyncReceiver.java	Mon Nov 13 16:13:11 2017 +0300
+++ b/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/Http1AsyncReceiver.java	Mon Nov 13 14:56:09 2017 +0000
@@ -374,7 +374,7 @@
         }
     }
 
-    // Callback: Consumer of ByteBufferReference
+    // Callback: Consumer of ByteBuffer
     private void asyncReceive(ByteBuffer buf) {
         debug.log(Level.DEBUG, "Putting %s bytes into the queue", buf.remaining());
         received.addAndGet(buf.remaining());
--- a/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/Http2Connection.java	Mon Nov 13 16:13:11 2017 +0300
+++ b/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/Http2Connection.java	Mon Nov 13 14:56:09 2017 +0000
@@ -46,8 +46,6 @@
 import java.util.function.Supplier;
 import javax.net.ssl.SSLEngine;
 import jdk.incubator.http.HttpConnection.HttpPublisher;
-import jdk.incubator.http.internal.common.ByteBufferPool;
-import jdk.incubator.http.internal.common.ByteBufferReference;
 import jdk.incubator.http.internal.common.FlowTube;
 import jdk.incubator.http.internal.common.FlowTube.TubeSubscriber;
 import jdk.incubator.http.internal.common.HttpHeadersImpl;
@@ -151,21 +149,21 @@
     // preface is sent will be buffered.
     private final class FramesController {
         volatile boolean prefaceSent;
-        volatile List<ByteBufferReference> pending;
+        volatile List<ByteBuffer> pending;
 
-        boolean processReceivedData(FramesDecoder decoder, ByteBufferReference buf)
+        boolean processReceivedData(FramesDecoder decoder, ByteBuffer buf)
                 throws IOException
         {
             // if preface is not sent, buffers data in the pending list
             if (!prefaceSent) {
                 debug.log(Level.DEBUG, "Preface is not sent: buffering %d",
-                          buf.get().remaining());
+                          buf.remaining());
                 synchronized (this) {
                     if (!prefaceSent) {
                         if (pending == null) pending = new ArrayList<>();
                         pending.add(buf);
                         debug.log(Level.DEBUG, () -> "there are now "
-                              + Utils.remaining(pending.toArray(Utils.EMPTY_BBR_ARRAY))
+                              + Utils.remaining(pending)
                               + " bytes buffered waiting for preface to be sent");
                         return false;
                     }
@@ -179,20 +177,19 @@
             // This ensures that later incoming buffers will not
             // be processed before we have flushed the pending queue.
             // No additional synchronization is therefore necessary here.
-            List<ByteBufferReference> pending = this.pending;
+            List<ByteBuffer> pending = this.pending;
             this.pending = null;
             if (pending != null) {
                 // flush pending data
                 debug.log(Level.DEBUG, () -> "Processing buffered data: "
-                      + Utils.remaining(pending.toArray(Utils.EMPTY_BBR_ARRAY)));
-                for (ByteBufferReference b : pending) {
+                      + Utils.remaining(pending));
+                for (ByteBuffer b : pending) {
                     decoder.decode(b);
                 }
             }
-            ByteBuffer b = buf.get();
             // push the received buffer to the frames decoder.
-            if (b != EMPTY_TRIGGER) {
-                debug.log(Level.DEBUG, "Processing %d", buf.get().remaining());
+            if (buf != EMPTY_TRIGGER) {
+                debug.log(Level.DEBUG, "Processing %d", buf.remaining());
                 decoder.decode(buf);
             }
             return true;
@@ -479,9 +476,9 @@
         return connection.publisher();
     }
 
-    private List<ByteBuffer> toBuffers(ByteBufferReference[] refs) {
-        return List.of(ByteBufferReference.toBuffers(refs));
-    }
+//    private List<ByteBuffer> toBuffers(ByteBufferReference[] refs) {
+//        return List.of(ByteBufferReference.toBuffers(refs));
+//    }
 
     private void decodeHeaders(HeaderFrame frame, DecodingCallback decoder)
             throws IOException
@@ -490,9 +487,11 @@
 
         boolean endOfHeaders = frame.getFlag(HeaderFrame.END_HEADERS);
 
-        ByteBufferReference[] buffers = frame.getHeaderBlock();
-        for (int i = 0; i < buffers.length; i++) {
-            hpackIn.decode(buffers[i].get(), endOfHeaders && (i == buffers.length - 1), decoder);
+        List<ByteBuffer> buffers = frame.getHeaderBlock();
+        int len = buffers.size();
+        for (int i = 0; i < len; i++) {
+            ByteBuffer b = buffers.get(i);
+            hpackIn.decode(b, endOfHeaders && (i == len - 1), decoder);
         }
     }
 
@@ -514,7 +513,7 @@
 //    }
 
     long count;
-    final void asyncReceive(ByteBufferReference buffer) {
+    final void asyncReceive(ByteBuffer buffer) {
         // We don't need to read anything and
         // we don't want to send anything back to the server
         // until the connection preface has been sent.
@@ -538,11 +537,10 @@
                     long c = ++count;
                     debug.log(Level.DEBUG, () -> "H2 Receiving Initial("
                         + c +"): " + b.remaining());
-                    framesController.processReceivedData(framesDecoder,
-                            ByteBufferReference.of(b));
+                    framesController.processReceivedData(framesDecoder, b);
                 }
             }
-            ByteBuffer b = buffer.get();
+            ByteBuffer b = buffer;
             // the Http2TubeSubscriber scheduler ensures that the order of incoming
             // buffers is preserved.
             if (b == EMPTY_TRIGGER) {
@@ -824,11 +822,11 @@
                      connection.channel().getLocalAddress(),
                      connection.address());
         SettingsFrame sf = client2.getClientSettings();
-        ByteBufferReference ref = framesEncoder.encodeConnectionPreface(PREFACE_BYTES, sf);
+        ByteBuffer buf = framesEncoder.encodeConnectionPreface(PREFACE_BYTES, sf);
         Log.logFrames(sf, "OUT");
         // send preface bytes and SettingsFrame together
         HttpPublisher publisher = publisher();
-        publisher.enqueue(List.of(ref.get()));
+        publisher.enqueue(List.of(buf));
         publisher.signalEnqueued();
         // mark preface sent.
         framesController.markPrefaceSent();
@@ -893,14 +891,14 @@
      * and CONTINUATION frames from the list and return the List<Http2Frame>.
      */
     private List<HeaderFrame> encodeHeaders(OutgoingHeaders<Stream<?>> frame) {
-        List<ByteBufferReference> buffers = encodeHeadersImpl(
+        List<ByteBuffer> buffers = encodeHeadersImpl(
                 getMaxSendFrameSize(),
                 frame.getAttachment().getRequestPseudoHeaders(),
                 frame.getUserHeaders(),
                 frame.getSystemHeaders());
 
         List<HeaderFrame> frames = new ArrayList<>(buffers.size());
-        Iterator<ByteBufferReference> bufIterator = buffers.iterator();
+        Iterator<ByteBuffer> bufIterator = buffers.iterator();
         HeaderFrame oframe = new HeadersFrame(frame.streamid(), frame.getFlags(), bufIterator.next());
         frames.add(oframe);
         while(bufIterator.hasNext()) {
@@ -915,12 +913,12 @@
     // There can be no concurrent access to this  buffer as all access to this buffer
     // and its content happen within a single critical code block section protected
     // by the sendLock. / (see sendFrame())
-    private final ByteBufferPool headerEncodingPool = new ByteBufferPool();
+    // private final ByteBufferPool headerEncodingPool = new ByteBufferPool();
 
-    private ByteBufferReference getHeaderBuffer(int maxFrameSize) {
-        ByteBufferReference ref = headerEncodingPool.get(maxFrameSize);
-        ref.get().limit(maxFrameSize);
-        return ref;
+    private ByteBuffer getHeaderBuffer(int maxFrameSize) {
+        ByteBuffer buf = ByteBuffer.allocate(maxFrameSize);
+        buf.limit(maxFrameSize);
+        return buf;
     }
 
     /*
@@ -934,29 +932,29 @@
      *     header field names MUST be converted to lowercase prior to their
      *     encoding in HTTP/2...
      */
-    private List<ByteBufferReference> encodeHeadersImpl(int maxFrameSize, HttpHeaders... headers) {
-        ByteBufferReference buffer = getHeaderBuffer(maxFrameSize);
-        List<ByteBufferReference> buffers = new ArrayList<>();
+    private List<ByteBuffer> encodeHeadersImpl(int maxFrameSize, HttpHeaders... headers) {
+        ByteBuffer buffer = getHeaderBuffer(maxFrameSize);
+        List<ByteBuffer> buffers = new ArrayList<>();
         for(HttpHeaders header : headers) {
             for (Map.Entry<String, List<String>> e : header.map().entrySet()) {
                 String lKey = e.getKey().toLowerCase();
                 List<String> values = e.getValue();
                 for (String value : values) {
                     hpackOut.header(lKey, value);
-                    while (!hpackOut.encode(buffer.get())) {
-                        buffer.get().flip();
+                    while (!hpackOut.encode(buffer)) {
+                        buffer.flip();
                         buffers.add(buffer);
                         buffer =  getHeaderBuffer(maxFrameSize);
                     }
                 }
             }
         }
-        buffer.get().flip();
+        buffer.flip();
         buffers.add(buffer);
         return buffers;
     }
 
-    private ByteBufferReference[] encodeHeaders(OutgoingHeaders<Stream<?>> oh, Stream<?> stream) {
+    private List<ByteBuffer> encodeHeaders(OutgoingHeaders<Stream<?>> oh, Stream<?> stream) {
         oh.streamid(stream.streamid);
         if (Log.headers()) {
             StringBuilder sb = new StringBuilder("HEADERS FRAME (stream=");
@@ -970,7 +968,7 @@
         return encodeFrames(frames);
     }
 
-    private ByteBufferReference[] encodeFrames(List<HeaderFrame> frames) {
+    private List<ByteBuffer> encodeFrames(List<HeaderFrame> frames) {
         if (Log.frames()) {
             frames.forEach(f -> Log.logFrames(f, "OUT"));
         }
@@ -1012,9 +1010,9 @@
                     OutgoingHeaders<Stream<?>> oh = (OutgoingHeaders<Stream<?>>) frame;
                     Stream<?> stream = registerNewStream(oh);
                     // provide protection from inserting unordered frames between Headers and Continuation
-                    publisher.enqueue(toBuffers(encodeHeaders(oh, stream)));
+                    publisher.enqueue(encodeHeaders(oh, stream));
                 } else {
-                    publisher.enqueue(toBuffers(encodeFrame(frame)));
+                    publisher.enqueue(encodeFrame(frame));
                 }
             }
             publisher.signalEnqueued();
@@ -1026,7 +1024,7 @@
         }
     }
 
-    private ByteBufferReference[] encodeFrame(Http2Frame frame) {
+    private List<ByteBuffer> encodeFrame(Http2Frame frame) {
         Log.logFrames(frame, "OUT");
         return framesEncoder.encodeFrame(frame);
     }
@@ -1034,7 +1032,7 @@
     void sendDataFrame(DataFrame frame) {
         try {
             HttpPublisher publisher = publisher();
-            publisher.enqueue(toBuffers(encodeFrame(frame)));
+            publisher.enqueue(encodeFrame(frame));
             publisher.signalEnqueued();
         } catch (IOException e) {
             if (!closed) {
@@ -1052,7 +1050,7 @@
     void sendUnorderedFrame(Http2Frame frame) {
         try {
             HttpPublisher publisher = publisher();
-            publisher.enqueueUnordered(toBuffers(encodeFrame(frame)));
+            publisher.enqueueUnordered(encodeFrame(frame));
             publisher.signalEnqueued();
         } catch (IOException e) {
             if (!closed) {
@@ -1090,7 +1088,7 @@
                     debug.log(Level.DEBUG,
                               "sending %d to Http2Connection.asyncReceive",
                               buffer.remaining());
-                    asyncReceive(ByteBufferReference.of(buffer));
+                    asyncReceive(buffer);
                 }
             } catch (Throwable t) {
                 Throwable x = error;
--- a/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/Stream.java	Mon Nov 13 16:13:11 2017 +0300
+++ b/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/Stream.java	Mon Nov 13 14:56:09 2017 +0000
@@ -163,12 +163,9 @@
             DataFrame df = (DataFrame)frame;
             boolean finished = df.getFlag(DataFrame.END_STREAM);
 
-            ByteBufferReference[] buffers = df.getData();
-            List<ByteBuffer> dsts = Arrays.stream(buffers)
-                .map(ByteBufferReference::get)
-                .filter(ByteBuffer::hasRemaining)
-                .collect(Collectors.collectingAndThen(toList(), Collections::unmodifiableList));
-            int size = (int)Utils.remaining(dsts);
+            List<ByteBuffer> buffers = df.getData();
+            List<ByteBuffer> dsts = Collections.unmodifiableList(buffers);
+            int size = Utils.remaining(dsts, Integer.MAX_VALUE);
             if (size == 0 && finished) {
                 inputQ.remove();
                 Log.logTrace("responseSubscriber.onComplete");
@@ -318,7 +315,7 @@
                 Log.logTrace("handling response (streamid={0})", streamid);
                 handleResponse();
                 if (hframe.getFlag(HeaderFrame.END_STREAM)) {
-                    receiveDataFrame(new DataFrame(streamid, DataFrame.END_STREAM, new ByteBufferReference[0]));
+                    receiveDataFrame(new DataFrame(streamid, DataFrame.END_STREAM, List.of()));
                 }
             }
         } else if (frame instanceof DataFrame) {
@@ -761,12 +758,12 @@
         int actualAmount = windowController.tryAcquire(requestAmount, streamid, this);
         if (actualAmount <= 0) return null;
         ByteBuffer outBuf = Utils.slice(buffer,  actualAmount);
-        DataFrame df = new DataFrame(streamid, 0 , ByteBufferReference.of(outBuf));
+        DataFrame df = new DataFrame(streamid, 0 , outBuf);
         return df;
     }
 
     private DataFrame getEmptyEndStreamDataFrame()  {
-        return new DataFrame(streamid, DataFrame.END_STREAM, new ByteBufferReference[0]);
+        return new DataFrame(streamid, DataFrame.END_STREAM, List.of());
     }
 
     /**
--- a/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/internal/frame/ContinuationFrame.java	Mon Nov 13 16:13:11 2017 +0300
+++ b/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/internal/frame/ContinuationFrame.java	Mon Nov 13 14:56:09 2017 +0000
@@ -25,18 +25,19 @@
 
 package jdk.incubator.http.internal.frame;
 
-import jdk.incubator.http.internal.common.ByteBufferReference;
+import java.nio.ByteBuffer;
+import java.util.List;
 
 public class ContinuationFrame extends HeaderFrame {
 
     public static final int TYPE = 0x9;
 
-    public ContinuationFrame(int streamid, int flags, ByteBufferReference[] headerBlocks) {
+    public ContinuationFrame(int streamid, int flags, List<ByteBuffer> headerBlocks) {
         super(streamid, flags, headerBlocks);
     }
 
-    public ContinuationFrame(int streamid, ByteBufferReference headersBlock) {
-        this(streamid, 0, new ByteBufferReference[]{headersBlock});
+    public ContinuationFrame(int streamid, ByteBuffer headersBlock) {
+        this(streamid, 0, List.of(headersBlock));
     }
 
     @Override
--- a/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/internal/frame/DataFrame.java	Mon Nov 13 16:13:11 2017 +0300
+++ b/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/internal/frame/DataFrame.java	Mon Nov 13 14:56:09 2017 +0000
@@ -25,9 +25,11 @@
 
 package jdk.incubator.http.internal.frame;
 
-import jdk.incubator.http.internal.common.ByteBufferReference;
 import jdk.incubator.http.internal.common.Utils;
 
+import java.nio.ByteBuffer;
+import java.util.List;
+
 public class DataFrame extends Http2Frame {
 
     public static final int TYPE = 0x0;
@@ -37,20 +39,20 @@
     public static final int PADDED = 0x8;
 
     private int padLength;
-    private final ByteBufferReference[] data;
+    private final List<ByteBuffer> data;
     private final int dataLength;
 
-    public DataFrame(int streamid, int flags, ByteBufferReference data) {
-        this(streamid, flags, new ByteBufferReference[]{data});
+    public DataFrame(int streamid, int flags, ByteBuffer data) {
+        this(streamid, flags, List.of(data));
     }
 
-    public DataFrame(int streamid, int flags, ByteBufferReference[] data) {
+    public DataFrame(int streamid, int flags, List<ByteBuffer> data) {
         super(streamid, flags);
         this.data = data;
         this.dataLength = Utils.remaining(data, Integer.MAX_VALUE);
     }
 
-    public DataFrame(int streamid, int flags, ByteBufferReference[] data, int padLength) {
+    public DataFrame(int streamid, int flags, List<ByteBuffer> data, int padLength) {
         this(streamid, flags, data);
         if (padLength > 0) {
             setPadLength(padLength);
@@ -78,7 +80,7 @@
         return super.flagAsString(flag);
     }
 
-    public ByteBufferReference[] getData() {
+    public List<ByteBuffer> getData() {
         return data;
     }
 
--- a/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/internal/frame/FramesDecoder.java	Mon Nov 13 16:13:11 2017 +0300
+++ b/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/internal/frame/FramesDecoder.java	Mon Nov 13 14:56:09 2017 +0000
@@ -25,7 +25,6 @@
 
 package jdk.incubator.http.internal.frame;
 
-import jdk.incubator.http.internal.common.ByteBufferReference;
 import jdk.incubator.http.internal.common.Log;
 import jdk.incubator.http.internal.common.Utils;
 
@@ -35,6 +34,7 @@
 import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Queue;
 
 /**
  * Frames Decoder
@@ -59,14 +59,14 @@
     private final FrameProcessor frameProcessor;
     private final int maxFrameSize;
 
-    private ByteBufferReference currentBuffer; // current buffer either null or hasRemaining
+    private ByteBuffer currentBuffer; // current buffer either null or hasRemaining
 
-    private final java.util.Queue<ByteBufferReference> tailBuffers = new ArrayDeque<>();
+    private final Queue<ByteBuffer> tailBuffers = new ArrayDeque<>();
     private int tailSize = 0;
 
     private boolean slicedToDataFrame = false;
 
-    private final List<ByteBufferReference> prepareToRelease = new ArrayList<>();
+    private final List<ByteBuffer> prepareToRelease = new ArrayList<>();
 
     // if true  - Frame Header was parsed (9 bytes consumed) and subsequent fields have meaning
     // otherwise - stopped at frames boundary
@@ -108,25 +108,23 @@
      * If there is enough data to perform frame decoding then, all buffers are
      * decoded and the FrameProcessor is invoked.
      */
-    public void decode(ByteBufferReference buffer) throws IOException {
-        int remaining = buffer.get().remaining();
+    public void decode(ByteBuffer buffer) throws IOException {
+        int remaining = buffer.remaining();
         DEBUG_LOGGER.log(Level.DEBUG, "decodes: %d", remaining);
         if (remaining > 0) {
             if (currentBuffer == null) {
                 currentBuffer = buffer;
             } else {
-                ByteBuffer cb = currentBuffer.get();
-                int freeSpace = cb.capacity() - cb.limit();
+                int limit = currentBuffer.limit();
+                int freeSpace = currentBuffer.capacity() - limit;
                 if (remaining <= COPY_THRESHOLD && freeSpace >= remaining) {
                     // append the new data to the unused space in the current buffer
-                    ByteBuffer b = buffer.get();
-                    int position = cb.position();
-                    int limit = cb.limit();
-                    cb.position(limit);
-                    cb.limit(limit + b.limit());
-                    cb.put(buffer.get());
-                    cb.position(position);
-                    buffer.clear();  // release the buffer, if it is a member of a pool
+                    ByteBuffer b = buffer;
+                    int position = currentBuffer.position();
+                    currentBuffer.position(limit);
+                    currentBuffer.limit(limit + b.limit());
+                    currentBuffer.put(b);
+                    currentBuffer.position(position);
                     DEBUG_LOGGER.log(Level.DEBUG, "copied: %d", remaining);
                 } else {
                     DEBUG_LOGGER.log(Level.DEBUG, "added: %d", remaining);
@@ -138,8 +136,7 @@
         DEBUG_LOGGER.log(Level.DEBUG, "Tail size is now: %d, current=",
                 tailSize,
                 (currentBuffer == null ? 0 :
-                  (currentBuffer.get() == null ? 0 :
-                   currentBuffer.get().remaining())));
+                   currentBuffer.remaining()));
         Http2Frame frame;
         while ((frame = nextFrame()) != null) {
             DEBUG_LOGGER.log(Level.DEBUG, "Got frame: %s", frame);
@@ -153,7 +150,7 @@
             if (currentBuffer == null) {
                 return null; // no data at all
             }
-            long available = currentBuffer.get().remaining() + tailSize;
+            long available = currentBuffer.remaining() + tailSize;
             if (!frameHeaderParsed) {
                 if (available >= Http2Frame.FRAME_HEADER_SIZE) {
                     parseFrameHeader();
@@ -172,7 +169,7 @@
                             Http2Frame.FRAME_HEADER_SIZE, available);
                 }
             }
-            available = currentBuffer == null ? 0 : currentBuffer.get().remaining() + tailSize;
+            available = currentBuffer == null ? 0 : currentBuffer.remaining() + tailSize;
             if ((frameLength == 0) ||
                     (currentBuffer != null && available >= frameLength)) {
                 Http2Frame frame = parseFrameBody();
@@ -191,7 +188,6 @@
     }
 
     private void frameProcessed() {
-        prepareToRelease.forEach(ByteBufferReference::clear);
         prepareToRelease.clear();
     }
 
@@ -207,29 +203,27 @@
 
     // move next buffer from tailBuffers to currentBuffer if required
     private void nextBuffer() {
-        if (!currentBuffer.get().hasRemaining()) {
+        if (!currentBuffer.hasRemaining()) {
             if (!slicedToDataFrame) {
                 prepareToRelease.add(currentBuffer);
             }
             slicedToDataFrame = false;
             currentBuffer = tailBuffers.poll();
             if (currentBuffer != null) {
-                tailSize -= currentBuffer.get().remaining();
+                tailSize -= currentBuffer.remaining();
             }
         }
     }
 
     public int getByte() {
-        ByteBuffer buf = currentBuffer.get();
-        int res = buf.get() & 0xff;
+        int res = currentBuffer.get() & 0xff;
         nextBuffer();
         return res;
     }
 
     public int getShort() {
-        ByteBuffer buf = currentBuffer.get();
-        if (buf.remaining() >= 2) {
-            int res = buf.getShort() & 0xffff;
+        if (currentBuffer.remaining() >= 2) {
+            int res = currentBuffer.getShort() & 0xffff;
             nextBuffer();
             return res;
         }
@@ -239,9 +233,8 @@
     }
 
     public int getInt() {
-        ByteBuffer buf = currentBuffer.get();
-        if (buf.remaining() >= 4) {
-            int res = buf.getInt();
+        if (currentBuffer.remaining() >= 4) {
+            int res = currentBuffer.getInt();
             nextBuffer();
             return res;
         }
@@ -257,9 +250,8 @@
         byte[] bytes = new byte[n];
         int offset = 0;
         while (n > 0) {
-            ByteBuffer buf = currentBuffer.get();
-            int length = Math.min(n, buf.remaining());
-            buf.get(bytes, offset, length);
+            int length = Math.min(n, currentBuffer.remaining());
+            currentBuffer.get(bytes, offset, length);
             offset += length;
             n -= length;
             nextBuffer();
@@ -268,36 +260,34 @@
 
     }
 
-    private ByteBufferReference[] getBuffers(boolean isDataFrame, int bytecount) {
-        List<ByteBufferReference> res = new ArrayList<>();
+    private List<ByteBuffer> getBuffers(boolean isDataFrame, int bytecount) {
+        List<ByteBuffer> res = new ArrayList<>();
         while (bytecount > 0) {
-            ByteBuffer buf = currentBuffer.get();
-            int remaining = buf.remaining();
+            int remaining = currentBuffer.remaining();
             int extract = Math.min(remaining, bytecount);
             ByteBuffer extractedBuf;
             if (isDataFrame) {
-                extractedBuf = Utils.slice(buf, extract);
+                extractedBuf = Utils.slice(currentBuffer, extract);
                 slicedToDataFrame = true;
             } else {
                 // Header frames here
                 // HPACK decoding should performed under lock and immediately after frame decoding.
                 // in that case it is safe to release original buffer,
                 // because of sliced buffer has a very short life
-                extractedBuf = Utils.slice(buf, extract);
+                extractedBuf = Utils.slice(currentBuffer, extract);
             }
-            res.add(ByteBufferReference.of(extractedBuf));
+            res.add(extractedBuf);
             bytecount -= extract;
             nextBuffer();
         }
-        return res.toArray(Utils.EMPTY_BBR_ARRAY);
+        return res;
     }
 
     public void skipBytes(int bytecount) {
         while (bytecount > 0) {
-            ByteBuffer buf = currentBuffer.get();
-            int remaining = buf.remaining();
+            int remaining = currentBuffer.remaining();
             int extract = Math.min(remaining, bytecount);
-            buf.position(buf.position() + extract);
+            currentBuffer.position(currentBuffer.position() + extract);
             bytecount -= remaining;
             nextBuffer();
         }
--- a/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/internal/frame/FramesEncoder.java	Mon Nov 13 16:13:11 2017 +0300
+++ b/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/internal/frame/FramesEncoder.java	Mon Nov 13 14:56:09 2017 +0000
@@ -25,12 +25,8 @@
 
 package jdk.incubator.http.internal.frame;
 
-import jdk.incubator.http.internal.common.ByteBufferReference;
-import jdk.incubator.http.internal.common.Utils;
-
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 
 /**
@@ -45,25 +41,24 @@
     public FramesEncoder() {
     }
 
-    public ByteBufferReference[] encodeFrames(List<HeaderFrame> frames) {
-        List<ByteBufferReference> refs = new ArrayList<>(frames.size() * 2);
+    public List<ByteBuffer> encodeFrames(List<HeaderFrame> frames) {
+        List<ByteBuffer> bufs = new ArrayList<>(frames.size() * 2);
         for (HeaderFrame f : frames) {
-            refs.addAll(Arrays.asList(encodeFrame(f)));
+            bufs.addAll(encodeFrame(f));
         }
-        return refs.toArray(Utils.EMPTY_BBR_ARRAY);
+        return bufs;
     }
 
-    public ByteBufferReference encodeConnectionPreface(byte[] preface, SettingsFrame frame) {
+    public ByteBuffer encodeConnectionPreface(byte[] preface, SettingsFrame frame) {
         final int length = frame.length();
-        ByteBufferReference ref = getBuffer(Http2Frame.FRAME_HEADER_SIZE + length + preface.length);
-        ByteBuffer buf = ref.get();
+        ByteBuffer buf = getBuffer(Http2Frame.FRAME_HEADER_SIZE + length + preface.length);
         buf.put(preface);
         putSettingsFrame(buf, frame, length);
         buf.flip();
-        return ref;
+        return buf;
     }
 
-    public ByteBufferReference[] encodeFrame(Http2Frame frame) {
+    public List<ByteBuffer> encodeFrame(Http2Frame frame) {
         switch (frame.type()) {
             case DataFrame.TYPE:
                 return encodeDataFrame((DataFrame) frame);
@@ -93,47 +88,45 @@
     private static final int NO_FLAGS = 0;
     private static final int ZERO_STREAM = 0;
 
-    private ByteBufferReference[] encodeDataFrame(DataFrame frame) {
+    private List<ByteBuffer> encodeDataFrame(DataFrame frame) {
         // non-zero stream
         assert frame.streamid() != 0;
-        ByteBufferReference ref = encodeDataFrameStart(frame);
+        ByteBuffer buf = encodeDataFrameStart(frame);
         if (frame.getFlag(DataFrame.PADDED)) {
-            return joinWithPadding(ref, frame.getData(), frame.getPadLength());
+            return joinWithPadding(buf, frame.getData(), frame.getPadLength());
         } else {
-            return join(ref, frame.getData());
+            return join(buf, frame.getData());
         }
     }
 
-    private ByteBufferReference encodeDataFrameStart(DataFrame frame) {
+    private ByteBuffer encodeDataFrameStart(DataFrame frame) {
         boolean isPadded = frame.getFlag(DataFrame.PADDED);
         final int length = frame.getDataLength() + (isPadded ? (frame.getPadLength() + 1) : 0);
-        ByteBufferReference ref = getBuffer(Http2Frame.FRAME_HEADER_SIZE + (isPadded ? 1 : 0));
-        ByteBuffer buf = ref.get();
+        ByteBuffer buf = getBuffer(Http2Frame.FRAME_HEADER_SIZE + (isPadded ? 1 : 0));
         putHeader(buf, length, DataFrame.TYPE, frame.getFlags(), frame.streamid());
         if (isPadded) {
             buf.put((byte) frame.getPadLength());
         }
         buf.flip();
-        return ref;
+        return buf;
     }
 
-    private ByteBufferReference[] encodeHeadersFrame(HeadersFrame frame) {
+    private List<ByteBuffer> encodeHeadersFrame(HeadersFrame frame) {
         // non-zero stream
         assert frame.streamid() != 0;
-        ByteBufferReference ref = encodeHeadersFrameStart(frame);
+        ByteBuffer buf = encodeHeadersFrameStart(frame);
         if (frame.getFlag(HeadersFrame.PADDED)) {
-            return joinWithPadding(ref, frame.getHeaderBlock(), frame.getPadLength());
+            return joinWithPadding(buf, frame.getHeaderBlock(), frame.getPadLength());
         } else {
-            return join(ref, frame.getHeaderBlock());
+            return join(buf, frame.getHeaderBlock());
         }
     }
 
-    private ByteBufferReference encodeHeadersFrameStart(HeadersFrame frame) {
+    private ByteBuffer encodeHeadersFrameStart(HeadersFrame frame) {
         boolean isPadded = frame.getFlag(HeadersFrame.PADDED);
         boolean hasPriority = frame.getFlag(HeadersFrame.PRIORITY);
         final int length = frame.getHeaderLength() + (isPadded ? (frame.getPadLength() + 1) : 0) + (hasPriority ? 5 : 0);
-        ByteBufferReference ref = getBuffer(Http2Frame.FRAME_HEADER_SIZE + (isPadded ? 1 : 0) + (hasPriority ? 5 : 0));
-        ByteBuffer buf = ref.get();
+        ByteBuffer buf = getBuffer(Http2Frame.FRAME_HEADER_SIZE + (isPadded ? 1 : 0) + (hasPriority ? 5 : 0));
         putHeader(buf, length, HeadersFrame.TYPE, frame.getFlags(), frame.streamid());
         if (isPadded) {
             buf.put((byte) frame.getPadLength());
@@ -142,51 +135,47 @@
             putPriority(buf, frame.getExclusive(), frame.getStreamDependency(), frame.getWeight());
         }
         buf.flip();
-        return ref;
+        return buf;
     }
 
-    private ByteBufferReference[] encodePriorityFrame(PriorityFrame frame) {
+    private List<ByteBuffer> encodePriorityFrame(PriorityFrame frame) {
         // non-zero stream; no flags
         assert frame.streamid() != 0;
         final int length = 5;
-        ByteBufferReference ref = getBuffer(Http2Frame.FRAME_HEADER_SIZE + length);
-        ByteBuffer buf = ref.get();
+        ByteBuffer buf = getBuffer(Http2Frame.FRAME_HEADER_SIZE + length);
         putHeader(buf, length, PriorityFrame.TYPE, NO_FLAGS, frame.streamid());
         putPriority(buf, frame.exclusive(), frame.streamDependency(), frame.weight());
         buf.flip();
-        return new ByteBufferReference[]{ref};
+        return List.of(buf);
     }
 
-    private ByteBufferReference[] encodeResetFrame(ResetFrame frame) {
+    private List<ByteBuffer> encodeResetFrame(ResetFrame frame) {
         // non-zero stream; no flags
         assert frame.streamid() != 0;
         final int length = 4;
-        ByteBufferReference ref = getBuffer(Http2Frame.FRAME_HEADER_SIZE + length);
-        ByteBuffer buf = ref.get();
+        ByteBuffer buf = getBuffer(Http2Frame.FRAME_HEADER_SIZE + length);
         putHeader(buf, length, ResetFrame.TYPE, NO_FLAGS, frame.streamid());
         buf.putInt(frame.getErrorCode());
         buf.flip();
-        return new ByteBufferReference[]{ref};
+        return List.of(buf);
     }
 
-    private ByteBufferReference[] encodeSettingsFrame(SettingsFrame frame) {
+    private List<ByteBuffer> encodeSettingsFrame(SettingsFrame frame) {
         // only zero stream
         assert frame.streamid() == 0;
         final int length = frame.length();
-        ByteBufferReference ref = getBuffer(Http2Frame.FRAME_HEADER_SIZE + length);
-        ByteBuffer buf = ref.get();
+        ByteBuffer buf = getBuffer(Http2Frame.FRAME_HEADER_SIZE + length);
         putSettingsFrame(buf, frame, length);
         buf.flip();
-        return new ByteBufferReference[]{ref};
+        return List.of(buf);
     }
 
-    private ByteBufferReference[] encodePushPromiseFrame(PushPromiseFrame frame) {
+    private List<ByteBuffer> encodePushPromiseFrame(PushPromiseFrame frame) {
         // non-zero stream
         assert frame.streamid() != 0;
         boolean isPadded = frame.getFlag(PushPromiseFrame.PADDED);
         final int length = frame.getHeaderLength() + (isPadded ? 5 : 4);
-        ByteBufferReference ref = getBuffer(Http2Frame.FRAME_HEADER_SIZE + (isPadded ? 5 : 4));
-        ByteBuffer buf = ref.get();
+        ByteBuffer buf = getBuffer(Http2Frame.FRAME_HEADER_SIZE + (isPadded ? 5 : 4));
         putHeader(buf, length, PushPromiseFrame.TYPE, frame.getFlags(), frame.streamid());
         if (isPadded) {
             buf.put((byte) frame.getPadLength());
@@ -195,31 +184,29 @@
         buf.flip();
 
         if (frame.getFlag(PushPromiseFrame.PADDED)) {
-            return joinWithPadding(ref, frame.getHeaderBlock(), frame.getPadLength());
+            return joinWithPadding(buf, frame.getHeaderBlock(), frame.getPadLength());
         } else {
-            return join(ref, frame.getHeaderBlock());
+            return join(buf, frame.getHeaderBlock());
         }
     }
 
-    private ByteBufferReference[] encodePingFrame(PingFrame frame) {
+    private List<ByteBuffer> encodePingFrame(PingFrame frame) {
         // only zero stream
         assert frame.streamid() == 0;
         final int length = 8;
-        ByteBufferReference ref = getBuffer(Http2Frame.FRAME_HEADER_SIZE + length);
-        ByteBuffer buf = ref.get();
+        ByteBuffer buf = getBuffer(Http2Frame.FRAME_HEADER_SIZE + length);
         putHeader(buf, length, PingFrame.TYPE, frame.getFlags(), ZERO_STREAM);
         buf.put(frame.getData());
         buf.flip();
-        return new ByteBufferReference[]{ref};
+        return List.of(buf);
     }
 
-    private ByteBufferReference[] encodeGoAwayFrame(GoAwayFrame frame) {
+    private List<ByteBuffer> encodeGoAwayFrame(GoAwayFrame frame) {
         // only zero stream; no flags
         assert frame.streamid() == 0;
         byte[] debugData = frame.getDebugData();
         final int length = 8 + debugData.length;
-        ByteBufferReference ref = getBuffer(Http2Frame.FRAME_HEADER_SIZE + length);
-        ByteBuffer buf = ref.get();
+        ByteBuffer buf = getBuffer(Http2Frame.FRAME_HEADER_SIZE + length);
         putHeader(buf, length, GoAwayFrame.TYPE, NO_FLAGS, ZERO_STREAM);
         buf.putInt(frame.getLastStream());
         buf.putInt(frame.getErrorCode());
@@ -227,45 +214,50 @@
             buf.put(debugData);
         }
         buf.flip();
-        return new ByteBufferReference[]{ref};
+        return List.of(buf);
     }
 
-    private ByteBufferReference[] encodeWindowUpdateFrame(WindowUpdateFrame frame) {
+    private List<ByteBuffer> encodeWindowUpdateFrame(WindowUpdateFrame frame) {
         // any stream; no flags
         final int length = 4;
-        ByteBufferReference ref = getBuffer(Http2Frame.FRAME_HEADER_SIZE + length);
-        ByteBuffer buf = ref.get();
+        ByteBuffer buf = getBuffer(Http2Frame.FRAME_HEADER_SIZE + length);
         putHeader(buf, length, WindowUpdateFrame.TYPE, NO_FLAGS, frame.streamid);
         buf.putInt(frame.getUpdate());
         buf.flip();
-        return new ByteBufferReference[]{ref};
+        return List.of(buf);
     }
 
-    private ByteBufferReference[] encodeContinuationFrame(ContinuationFrame frame) {
+    private List<ByteBuffer> encodeContinuationFrame(ContinuationFrame frame) {
         // non-zero stream;
         assert frame.streamid() != 0;
         final int length = frame.getHeaderLength();
-        ByteBufferReference ref = getBuffer(Http2Frame.FRAME_HEADER_SIZE);
-        ByteBuffer buf = ref.get();
+        ByteBuffer buf = getBuffer(Http2Frame.FRAME_HEADER_SIZE);
         putHeader(buf, length, ContinuationFrame.TYPE, frame.getFlags(), frame.streamid());
         buf.flip();
-        return join(ref, frame.getHeaderBlock());
+        return join(buf, frame.getHeaderBlock());
     }
 
-    private ByteBufferReference[] joinWithPadding(ByteBufferReference ref, ByteBufferReference[] data, int padLength) {
-        ByteBufferReference[] references = new ByteBufferReference[2 + data.length];
-        references[0] = ref;
-        System.arraycopy(data, 0, references, 1, data.length);
-        assert references[references.length - 1] == null;
-        references[references.length - 1] = getPadding(padLength);
-        return references;
+    private List<ByteBuffer> joinWithPadding(ByteBuffer buf, List<ByteBuffer> data, int padLength) {
+        int len = data.size();
+        if (len == 0) return List.of(buf, getPadding(padLength));
+        else if (len == 1) return List.of(buf, data.get(0), getPadding(padLength));
+        else if (len == 2) return List.of(buf, data.get(0), data.get(1), getPadding(padLength));
+        List<ByteBuffer> res = new ArrayList<>(len+2);
+        res.add(buf);
+        res.addAll(data);
+        res.add(getPadding(padLength));
+        return res;
     }
 
-    private ByteBufferReference[] join(ByteBufferReference ref, ByteBufferReference[] data) {
-        ByteBufferReference[] references = new ByteBufferReference[1 + data.length];
-        references[0] = ref;
-        System.arraycopy(data, 0, references, 1, data.length);
-        return references;
+    private List<ByteBuffer> join(ByteBuffer buf, List<ByteBuffer> data) {
+        int len = data.size();
+        if (len == 0) return List.of(buf);
+        else if (len == 1) return List.of(buf, data.get(0));
+        else if (len == 2) return List.of(buf, data.get(0), data.get(1));
+        List<ByteBuffer> joined = new ArrayList<>(len + 1);
+        joined.add(buf);
+        joined.addAll(data);
+        return joined;
     }
 
     private void putSettingsFrame(ByteBuffer buf, SettingsFrame frame, int length) {
@@ -287,15 +279,15 @@
         buf.put((byte) weight);
     }
 
-    private ByteBufferReference getBuffer(int capacity) {
-        return ByteBufferReference.of(ByteBuffer.allocate(capacity));
+    private ByteBuffer getBuffer(int capacity) {
+        return ByteBuffer.allocate(capacity);
     }
 
-    public ByteBufferReference getPadding(int length) {
+    public ByteBuffer getPadding(int length) {
         if (length > 255) {
             throw new IllegalArgumentException("Padding too big");
         }
-        return ByteBufferReference.of(ByteBuffer.allocate(length)); // zeroed!
+        return ByteBuffer.allocate(length); // zeroed!
     }
 
 }
--- a/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/internal/frame/HeaderFrame.java	Mon Nov 13 16:13:11 2017 +0300
+++ b/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/internal/frame/HeaderFrame.java	Mon Nov 13 14:56:09 2017 +0000
@@ -25,25 +25,23 @@
 
 package jdk.incubator.http.internal.frame;
 
-import jdk.incubator.http.internal.common.ByteBufferReference;
 import jdk.incubator.http.internal.common.Utils;
 
+import java.nio.ByteBuffer;
+import java.util.List;
+
 /**
  * Either a HeadersFrame or a ContinuationFrame
  */
 public abstract class HeaderFrame extends Http2Frame {
 
     final int headerLength;
-    final ByteBufferReference[] headerBlocks;
+    final List<ByteBuffer> headerBlocks;
 
     public static final int END_STREAM = 0x1;
     public static final int END_HEADERS = 0x4;
 
-//    public HeaderFrame(int streamid, int flags, ByteBufferReference headerBlock) {
-//        this(streamid, flags, new ByteBufferReference[]{headerBlock});
-//    }
-
-    public HeaderFrame(int streamid, int flags, ByteBufferReference[] headerBlocks) {
+    public HeaderFrame(int streamid, int flags, List<ByteBuffer> headerBlocks) {
         super(streamid, flags);
         this.headerBlocks = headerBlocks;
         this.headerLength = Utils.remaining(headerBlocks, Integer.MAX_VALUE);
@@ -61,7 +59,7 @@
     }
 
 
-    public ByteBufferReference[] getHeaderBlock() {
+    public List<ByteBuffer> getHeaderBlock() {
         return headerBlocks;
     }
 
--- a/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/internal/frame/HeadersFrame.java	Mon Nov 13 16:13:11 2017 +0300
+++ b/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/internal/frame/HeadersFrame.java	Mon Nov 13 14:56:09 2017 +0000
@@ -25,7 +25,8 @@
 
 package jdk.incubator.http.internal.frame;
 
-import jdk.incubator.http.internal.common.ByteBufferReference;
+import java.nio.ByteBuffer;
+import java.util.List;
 
 public class HeadersFrame extends HeaderFrame {
 
@@ -42,19 +43,19 @@
     private int weight;
     private boolean exclusive;
 
-    public HeadersFrame(int streamid, int flags, ByteBufferReference[] headerBlocks, int padLength) {
+    public HeadersFrame(int streamid, int flags, List<ByteBuffer> headerBlocks, int padLength) {
         super(streamid, flags, headerBlocks);
         if (padLength > 0) {
             setPadLength(padLength);
         }
     }
 
-    public HeadersFrame(int streamid, int flags, ByteBufferReference[] headerBlocks) {
+    public HeadersFrame(int streamid, int flags, List<ByteBuffer> headerBlocks) {
         super(streamid, flags, headerBlocks);
     }
 
-    public HeadersFrame(int streamid, int flags, ByteBufferReference headerBlock) {
-        this(streamid, flags, new ByteBufferReference[]{headerBlock});
+    public HeadersFrame(int streamid, int flags, ByteBuffer headerBlock) {
+        this(streamid, flags, List.of(headerBlock));
     }
 
     @Override
--- a/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/internal/frame/PushPromiseFrame.java	Mon Nov 13 16:13:11 2017 +0300
+++ b/src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/internal/frame/PushPromiseFrame.java	Mon Nov 13 14:56:09 2017 +0000
@@ -25,7 +25,8 @@
 
 package jdk.incubator.http.internal.frame;
 
-import jdk.incubator.http.internal.common.ByteBufferReference;
+import java.nio.ByteBuffer;
+import java.util.List;
 
 public class PushPromiseFrame extends HeaderFrame {
 
@@ -38,7 +39,7 @@
     public static final int END_HEADERS = 0x4;
     public static final int PADDED = 0x8;
 
-    public PushPromiseFrame(int streamid, int flags, int promisedStream, ByteBufferReference[] buffers, int padLength) {
+    public PushPromiseFrame(int streamid, int flags, int promisedStream, List<ByteBuffer> buffers, int padLength) {
         super(streamid, flags, buffers);
         this.promisedStream = promisedStream;
         if(padLength > 0 ) {
--- a/test/jdk/java/net/httpclient/http2/server/BodyInputStream.java	Mon Nov 13 16:13:11 2017 +0300
+++ b/test/jdk/java/net/httpclient/http2/server/BodyInputStream.java	Mon Nov 13 14:56:09 2017 +0000
@@ -23,8 +23,8 @@
 
 import java.io.*;
 import java.nio.ByteBuffer;
+import java.util.List;
 
-import jdk.incubator.http.internal.common.ByteBufferReference;
 import jdk.incubator.http.internal.common.Utils;
 import jdk.incubator.http.internal.frame.DataFrame;
 import jdk.incubator.http.internal.frame.Http2Frame;
@@ -86,13 +86,13 @@
                 if (df == null) {
                     return null;
                 }
-                ByteBufferReference[] data = df.getData();
+                List<ByteBuffer> data = df.getData();
                 long len = Utils.remaining(data);
                 if ((len == 0) && eof) {
                     return null;
                 }
 
-                buffers = ByteBufferReference.toBuffers(data);
+                buffers = data.toArray(Utils.EMPTY_BB_ARRAY);
                 nextIndex = 0;
             }
             buffer = buffers[nextIndex++];
--- a/test/jdk/java/net/httpclient/http2/server/BodyOutputStream.java	Mon Nov 13 16:13:11 2017 +0300
+++ b/test/jdk/java/net/httpclient/http2/server/BodyOutputStream.java	Mon Nov 13 14:56:09 2017 +0000
@@ -24,7 +24,6 @@
 import java.io.*;
 import java.nio.ByteBuffer;
 
-import jdk.incubator.http.internal.common.ByteBufferReference;
 import jdk.incubator.http.internal.frame.DataFrame;
 
 /**
@@ -99,7 +98,7 @@
         buffer.put(buf, offset, len);
         buffer.flip();
         assert streamid != 0;
-        DataFrame df = new DataFrame(streamid, flags, ByteBufferReference.of(buffer));
+        DataFrame df = new DataFrame(streamid, flags, buffer);
         outputQ.put(df);
     }
 
--- a/test/jdk/java/net/httpclient/http2/server/Http2TestServerConnection.java	Mon Nov 13 16:13:11 2017 +0300
+++ b/test/jdk/java/net/httpclient/http2/server/Http2TestServerConnection.java	Mon Nov 13 14:56:09 2017 +0000
@@ -38,7 +38,6 @@
 import java.util.*;
 import java.util.concurrent.ExecutorService;
 import java.util.function.Consumer;
-import jdk.incubator.http.internal.common.ByteBufferReference;
 import jdk.incubator.http.internal.common.HttpHeadersImpl;
 import jdk.incubator.http.internal.frame.DataFrame;
 import jdk.incubator.http.internal.frame.FramesDecoder;
@@ -194,8 +193,8 @@
                 new byte[] {0, 0, (byte)payload.length, 4, 0, 0, 0, 0, 0});
         List<Http2Frame> frames = new ArrayList<>();
         FramesDecoder reader = new FramesDecoder(frames::add);
-        reader.decode(ByteBufferReference.of(bb0));
-        reader.decode(ByteBufferReference.of(bb1));
+        reader.decode(bb0);
+        reader.decode(bb1);
         if (frames.size()!=1)
             throw new IOException("Expected 1 frame got "+frames.size()) ;
         Http2Frame frame = frames.get(0);
@@ -235,11 +234,10 @@
     }
 
     private void writeFrame(Http2Frame frame) throws IOException {
-        ByteBufferReference[] refs = new FramesEncoder().encodeFrame(frame);
+        List<ByteBuffer> bufs = new FramesEncoder().encodeFrame(frame);
         //System.err.println("TestServer: Writing frame " + frame.toString());
         int c = 0;
-        for (ByteBufferReference ref : refs) {
-            ByteBuffer buf = ref.get();
+        for (ByteBuffer buf : bufs) {
             byte[] ba = buf.array();
             int start = buf.arrayOffset() + buf.position();
             c += buf.remaining();
@@ -306,9 +304,9 @@
         };
 
         for (HeaderFrame frame : frames) {
-            ByteBufferReference[] buffers = frame.getHeaderBlock();
-            for (ByteBufferReference buffer : buffers) {
-                hpackIn.decode(buffer.get(), false, cb);
+            List<ByteBuffer> buffers = frame.getHeaderBlock();
+            for (ByteBuffer buffer : buffers) {
+                hpackIn.decode(buffer, false, cb);
             }
         }
         hpackIn.decode(EMPTY_BUFFER, true, cb);
@@ -530,7 +528,7 @@
         }
     }
 
-    ByteBufferReference[] encodeHeaders(HttpHeadersImpl headers) {
+    List<ByteBuffer> encodeHeaders(HttpHeadersImpl headers) {
         List<ByteBuffer> buffers = new LinkedList<>();
 
         ByteBuffer buf = getBuffer();
@@ -552,7 +550,7 @@
         }
         buf.flip();
         buffers.add(buf);
-        return ByteBufferReference.toReferences(buffers.toArray(bbarray));
+        return buffers;
     }
 
     static void closeIgnore(Closeable c) {
@@ -595,7 +593,11 @@
 
     private void handlePush(OutgoingPushPromise op) throws IOException {
         int promisedStreamid = nextPushStreamId;
-        PushPromiseFrame pp = new PushPromiseFrame(op.parentStream, HeaderFrame.END_HEADERS, promisedStreamid, encodeHeaders(op.headers), 0);
+        PushPromiseFrame pp = new PushPromiseFrame(op.parentStream,
+                                                   HeaderFrame.END_HEADERS,
+                                                   promisedStreamid,
+                                                   encodeHeaders(op.headers),
+                                                   0);
         pushStreams.add(promisedStreamid);
         nextPushStreamId += 2;
         pp.streamid(op.parentStream);
@@ -653,8 +655,8 @@
             throw new IOException("Error reading frame");
         List<Http2Frame> frames = new ArrayList<>();
         FramesDecoder reader = new FramesDecoder(frames::add);
-        reader.decode(ByteBufferReference.of(ByteBuffer.wrap(buf)));
-        reader.decode(ByteBufferReference.of(ByteBuffer.wrap(rest)));
+        reader.decode(ByteBuffer.wrap(buf));
+        reader.decode(ByteBuffer.wrap(rest));
         if (frames.size()!=1)
             throw new IOException("Expected 1 frame got "+frames.size()) ;
 
@@ -791,7 +793,7 @@
     @SuppressWarnings({"rawtypes","unchecked"})
     void addRequestBodyToQueue(String body, Queue q) throws IOException {
         ByteBuffer buf = ByteBuffer.wrap(body.getBytes(StandardCharsets.US_ASCII));
-        DataFrame df = new DataFrame(1, DataFrame.END_STREAM, ByteBufferReference.of(buf));
+        DataFrame df = new DataFrame(1, DataFrame.END_STREAM, buf);
         // only used for primordial stream
         q.put(df);
     }
--- a/test/jdk/java/net/httpclient/whitebox/jdk.incubator.httpclient/jdk/incubator/http/ConnectionPoolTest.java	Mon Nov 13 16:13:11 2017 +0300
+++ b/test/jdk/java/net/httpclient/whitebox/jdk.incubator.httpclient/jdk/incubator/http/ConnectionPoolTest.java	Mon Nov 13 14:56:09 2017 +0000
@@ -42,7 +42,6 @@
 import java.time.temporal.ChronoUnit;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLParameters;
-import jdk.incubator.http.internal.common.ByteBufferReference;
 import jdk.incubator.http.internal.common.FlowTube;
 
 /**
@@ -69,7 +68,7 @@
     }
 
     public static void testCacheCleaners() throws Exception {
-        ConnectionPool pool = new ConnectionPool();
+        ConnectionPool pool = new ConnectionPool(666);
         HttpClient client = new HttpClientStub(pool);
         InetSocketAddress proxy = InetSocketAddress.createUnresolved("bar", 80);
         System.out.println("Adding 10 connections to pool");