Description: support JRE8

from https://jira.mongodb.org/browse/JAVA-2559:

"Java 9 introduces overridden methods with covariant return types for the
following methods in java.nio.ByteBuffer that are used by the driver:

    position
    limit
    flip
    clear

In Java 9 they all now return ByteBuffer, whereas the methods they
override return Buffer, resulting in exceptions like this when executing
on Java 8 and lower:

java.lang.NoSuchMethodError:
java.nio.ByteBuffer.limit(I)Ljava/nio/ByteBuffer

This is because the generated byte code includes the static return type
of the method, which is not found on Java 8 and lower because the
overloaded methods with covariant return types don't exist.

The solution is to cast ByteBuffer instances to Buffer before calling
the method."

In addition to ByteBuffer, also Charbuffer needs changes, and mark() added
to the list of methods.


--- a/java/org/apache/catalina/connector/InputBuffer.java
+++ b/java/org/apache/catalina/connector/InputBuffer.java
@@ -375,11 +375,11 @@ public class InputBuffer extends Reader
             return -1;
         }
         int n = Math.min(to.remaining(), bb.remaining());
-        int orgLimit = bb.limit();
-        bb.limit(bb.position() + n);
+        int orgLimit = ((Buffer) bb).limit();
+        ((Buffer) bb).limit(((Buffer) bb).position() + n);
         to.put(bb);
-        bb.limit(orgLimit);
-        to.limit(to.position()).position(to.position() - n);
+        ((Buffer) bb).limit(orgLimit);
+        ((Buffer) to).limit(((Buffer) to).position()).position(((Buffer) to).position() - n);
         return n;
     }
 
@@ -415,7 +415,7 @@ public class InputBuffer extends Reader
         } else {
             // Make sure there's enough space in the worst case
             makeSpace(bb.remaining());
-            if ((cb.capacity() - cb.limit()) == 0 && bb.remaining() != 0) {
+            if ((cb.capacity() - ((Buffer) cb).limit()) == 0 && bb.remaining() != 0) {
                 // We went over the limit
                 clear(cb);
                 markPos = -1;
@@ -487,11 +487,11 @@ public class InputBuffer extends Reader
         long nRead = 0;
         while (nRead < n) {
             if (cb.remaining() >= n) {
-                cb.position(cb.position() + (int) n);
+                ((Buffer) cb).position(((Buffer) cb).position() + (int) n);
                 nRead = n;
             } else {
                 nRead += cb.remaining();
-                cb.position(cb.limit());
+                ((Buffer) cb).position(((Buffer) cb).limit());
                 int nb = realReadChars();
                 if (nb < 0) {
                     break;
@@ -530,13 +530,13 @@ public class InputBuffer extends Reader
         if (cb.remaining() <= 0) {
             clear(cb);
         } else {
-            if ((cb.capacity() > (2 * size)) && (cb.remaining()) < (cb.position())) {
+            if ((cb.capacity() > (2 * size)) && (cb.remaining()) < (((Buffer) cb).position())) {
                 cb.compact();
-                cb.flip();
+                ((Buffer) cb).flip();
             }
         }
-        readLimit = cb.position() + readAheadLimit + size;
-        markPos = cb.position();
+        readLimit = ((Buffer) cb).position() + readAheadLimit + size;
+        markPos = ((Buffer) cb).position();
     }
 
 
@@ -553,7 +553,7 @@ public class InputBuffer extends Reader
                 markPos = -1;
                 throw new IOException();
             } else {
-                cb.position(markPos);
+                ((Buffer) cb).position(markPos);
             }
         } else {
             clear(bb);
@@ -662,7 +662,7 @@ public class InputBuffer extends Reader
     }
 
     private void makeSpace(int count) {
-        int desiredSize = cb.limit() + count;
+        int desiredSize = ((Buffer) cb).limit() + count;
         if(desiredSize > readLimit) {
             desiredSize = readLimit;
         }
@@ -681,11 +681,11 @@ public class InputBuffer extends Reader
         }
 
         CharBuffer tmp = CharBuffer.allocate(newSize);
-        int oldPosition = cb.position();
-        cb.position(0);
+        int oldPosition = ((Buffer) cb).position();
+        ((Buffer) cb).position(0);
         tmp.put(cb);
-        tmp.flip();
-        tmp.position(oldPosition);
+        ((Buffer) tmp).flip();
+        ((Buffer) tmp).position(oldPosition);
         cb = tmp;
         tmp = null;
     }
--- a/java/org/apache/catalina/connector/OutputBuffer.java
+++ b/java/org/apache/catalina/connector/OutputBuffer.java
@@ -732,7 +732,7 @@ public class OutputBuffer extends Writer
      */
     public void append(char src[], int off, int len) throws IOException {
         // if we have limit and we're below
-        if(len <= cb.capacity() - cb.limit()) {
+        if(len <= cb.capacity() - ((Buffer) cb).limit()) {
             transfer(src, off, len, cb);
             return;
         }
@@ -798,12 +798,12 @@ public class OutputBuffer extends Writer
         }
 
         int limit = bb.capacity();
-        int fromLimit = from.limit();
+        int fromLimit = ((Buffer) from).limit();
         while (from.remaining() >= limit) {
-            from.limit(from.position() + limit);
+            ((Buffer) from).limit(((Buffer) from).position() + limit);
             realWriteBytes(from.slice());
-            from.position(from.limit());
-            from.limit(fromLimit);
+            ((Buffer) from).position(((Buffer) from).limit());
+            ((Buffer) from).limit(fromLimit);
         }
 
         if (from.remaining() > 0) {
@@ -867,10 +867,10 @@ public class OutputBuffer extends Writer
         toWriteMode(to);
         int max = Math.min(from.remaining(), to.remaining());
         if (max > 0) {
-            int fromLimit = from.limit();
-            from.limit(from.position() + max);
+            int fromLimit = ((Buffer) from).limit();
+            ((Buffer) from).limit(((Buffer) from).position() + max);
             to.put(from);
-            from.limit(fromLimit);
+            ((Buffer) from).limit(fromLimit);
         }
         toReadMode(to);
     }
--- a/java/org/apache/catalina/tribes/transport/nio/NioReplicationTask.java
+++ b/java/org/apache/catalina/tribes/transport/nio/NioReplicationTask.java
@@ -18,6 +18,7 @@
 package org.apache.catalina.tribes.transport.nio;
 import java.io.IOException;
 import java.net.SocketAddress;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.channels.CancelledKeyException;
 import java.nio.channels.DatagramChannel;
@@ -80,7 +81,7 @@ public class NioReplicationTask extends
                 buffer = ByteBuffer.allocate(size);
             }
         } else {
-            buffer.clear();
+            ((Buffer) buffer).clear();
         }
         if (key == null) {
             return; // just in case
@@ -156,30 +157,30 @@ public class NioReplicationTask extends
         reader.access();
         ReadableByteChannel channel = (ReadableByteChannel) key.channel();
         int count=-1;
-        buffer.clear();         // make buffer empty
+        ((Buffer) buffer).clear();         // make buffer empty
         SocketAddress saddr = null;
 
         if (channel instanceof SocketChannel) {
             // loop while data available, channel is non-blocking
             while ((count = channel.read (buffer)) > 0) {
-                buffer.flip();      // make buffer readable
+                ((Buffer) buffer).flip();      // make buffer readable
                 if ( buffer.hasArray() )
                     reader.append(buffer.array(),0,count,false);
                 else
                     reader.append(buffer,count,false);
-                buffer.clear();     // make buffer empty
+                ((Buffer) buffer).clear();     // make buffer empty
                 //do we have at least one package?
                 if ( reader.hasPackage() ) break;
             }
         } else if (channel instanceof DatagramChannel) {
             DatagramChannel dchannel = (DatagramChannel)channel;
             saddr = dchannel.receive(buffer);
-            buffer.flip();      // make buffer readable
+            ((Buffer) buffer).flip();      // make buffer readable
             if ( buffer.hasArray() )
-                reader.append(buffer.array(),0,buffer.limit()-buffer.position(),false);
+                reader.append(buffer.array(),0,((Buffer) buffer).limit()-((Buffer) buffer).position(),false);
             else
-                reader.append(buffer,buffer.limit()-buffer.position(),false);
-            buffer.clear();     // make buffer empty
+                reader.append(buffer,((Buffer) buffer).limit()-((Buffer) buffer).position(),false);
+            ((Buffer) buffer).clear();     // make buffer empty
             //did we get a package
             count = reader.hasPackage()?1:-1;
         }
--- a/java/org/apache/catalina/tribes/transport/nio/NioSender.java
+++ b/java/org/apache/catalina/tribes/transport/nio/NioSender.java
@@ -20,6 +20,7 @@ package org.apache.catalina.tribes.trans
 import java.io.EOFException;
 import java.io.IOException;
 import java.net.InetSocketAddress;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.channels.DatagramChannel;
 import java.nio.channels.SelectionKey;
@@ -173,9 +174,9 @@ public class NioSender extends AbstractS
         if ( read == -1 ) throw new IOException(sm.getString("nioSender.unable.receive.ack"));
         //no data read
         else if ( read == 0 ) return false;
-        readbuf.flip();
+        ((Buffer) readbuf).flip();
         ackbuf.append(readbuf,read);
-        readbuf.clear();
+        ((Buffer) readbuf).clear();
         if (ackbuf.doesPackageExist() ) {
             byte[] ackcmd = ackbuf.extractDataPackage(true).getBytes();
             boolean ack = Arrays.equals(ackcmd,org.apache.catalina.tribes.transport.Constants.ACK_DATA);
@@ -225,12 +226,12 @@ public class NioSender extends AbstractS
         if ( readbuf == null ) {
             readbuf = getReadBuffer();
         } else {
-            readbuf.clear();
+            ((Buffer) readbuf).clear();
         }
         if ( writebuf == null ) {
             writebuf = getWriteBuffer();
         } else {
-            writebuf.clear();
+            ((Buffer) writebuf).clear();
         }
 
         if (isUdpBased()) {
@@ -317,8 +318,8 @@ public class NioSender extends AbstractS
         if ( isConnected() && readbuf == null) {
             readbuf = getReadBuffer();
         }
-        if ( readbuf != null ) readbuf.clear();
-        if ( writebuf != null ) writebuf.clear();
+        if ( readbuf != null ) ((Buffer) readbuf).clear();
+        if ( writebuf != null ) ((Buffer) writebuf).clear();
         current = null;
         ackbuf.clear();
         remaining = 0;
@@ -357,7 +358,7 @@ public class NioSender extends AbstractS
                 remaining = length;
                 ackbuf.clear();
                 if (writebuf != null) {
-                    writebuf.clear();
+                    ((Buffer) writebuf).clear();
                 } else {
                     writebuf = getBuffer(length);
                 }
@@ -367,7 +368,7 @@ public class NioSender extends AbstractS
 
                 // TODO use ByteBuffer.wrap to avoid copying the data.
                 writebuf.put(data,offset,length);
-                writebuf.flip();
+                ((Buffer) writebuf).flip();
                 if (isConnected()) {
                     if (isUdpBased())
                         dataChannel.register(getSelector(), SelectionKey.OP_WRITE, this);
--- a/java/org/apache/coyote/ajp/AjpProcessor.java
+++ b/java/org/apache/coyote/ajp/AjpProcessor.java
@@ -21,6 +21,7 @@ import java.io.EOFException;
 import java.io.IOException;
 import java.io.InterruptedIOException;
 import java.net.InetAddress;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.security.NoSuchProviderException;
 import java.security.cert.CertificateFactory;
@@ -1368,7 +1369,7 @@ public class AjpProcessor extends Abstra
 
             responseMessage.reset();
             responseMessage.appendByte(Constants.JK_AJP13_SEND_BODY_CHUNK);
-            chunk.limit(chunk.position() + thisTime);
+            ((Buffer) chunk).limit(((Buffer) chunk).position() + thisTime);
             responseMessage.appendBytes(chunk);
             responseMessage.end();
             socketWrapper.write(blocking, responseMessage.getBuffer(), 0, responseMessage.getLen());
--- a/java/org/apache/coyote/http11/Http11InputBuffer.java
+++ b/java/org/apache/coyote/http11/Http11InputBuffer.java
@@ -18,6 +18,7 @@ package org.apache.coyote.http11;
 
 import java.io.EOFException;
 import java.io.IOException;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 
@@ -277,7 +278,7 @@ public class Http11InputBuffer implement
             activeFilters[i].recycle();
         }
 
-        byteBuffer.limit(0).position(0);
+        ((Buffer) byteBuffer).limit(0).position(0);
         lastActiveFilter = -1;
         parsingHeader = true;
         swallowInput = true;
@@ -301,14 +302,14 @@ public class Http11InputBuffer implement
     void nextRequest() {
         request.recycle();
 
-        if (byteBuffer.position() > 0) {
+        if (((Buffer) byteBuffer).position() > 0) {
             if (byteBuffer.remaining() > 0) {
                 // Copy leftover bytes to the beginning of the buffer
                 byteBuffer.compact();
-                byteBuffer.flip();
+                ((Buffer) byteBuffer).flip();
             } else {
                 // Reset position and limit to 0
-                byteBuffer.position(0).limit(0);
+                ((Buffer) byteBuffer).position(0).limit(0);
             }
         }
 
@@ -357,7 +358,7 @@ public class Http11InputBuffer implement
             do {
 
                 // Read new bytes if needed
-                if (byteBuffer.position() >= byteBuffer.limit()) {
+                if (((Buffer) byteBuffer).position() >= ((Buffer) byteBuffer).limit()) {
                     if (keptAlive) {
                         // Haven't read any request data yet so use the keep-alive
                         // timeout.
@@ -372,7 +373,7 @@ public class Http11InputBuffer implement
                     // Switch to the socket timeout.
                     wrapper.setReadTimeout(wrapper.getEndpoint().getConnectionTimeout());
                 }
-                if (!keptAlive && byteBuffer.position() == 0 && byteBuffer.limit() >= CLIENT_PREFACE_START.length - 1) {
+                if (!keptAlive && ((Buffer) byteBuffer).position() == 0 && ((Buffer) byteBuffer).limit() >= CLIENT_PREFACE_START.length - 1) {
                     boolean prefaceMatch = true;
                     for (int i = 0; i < CLIENT_PREFACE_START.length && prefaceMatch; i++) {
                         if (CLIENT_PREFACE_START[i] != byteBuffer.get(i)) {
@@ -392,9 +393,9 @@ public class Http11InputBuffer implement
                 }
                 chr = byteBuffer.get();
             } while ((chr == Constants.CR) || (chr == Constants.LF));
-            byteBuffer.position(byteBuffer.position() - 1);
+            ((Buffer) byteBuffer).position(((Buffer) byteBuffer).position() - 1);
 
-            parsingRequestLineStart = byteBuffer.position();
+            parsingRequestLineStart = ((Buffer) byteBuffer).position();
             parsingRequestLinePhase = 2;
             if (log.isDebugEnabled()) {
                 log.debug("Received ["
@@ -409,20 +410,20 @@ public class Http11InputBuffer implement
             boolean space = false;
             while (!space) {
                 // Read new bytes if needed
-                if (byteBuffer.position() >= byteBuffer.limit()) {
+                if (((Buffer) byteBuffer).position() >= ((Buffer) byteBuffer).limit()) {
                     if (!fill(false)) // request line parsing
                         return false;
                 }
                 // Spec says method name is a token followed by a single SP but
                 // also be tolerant of multiple SP and/or HT.
-                int pos = byteBuffer.position();
+                int pos = ((Buffer) byteBuffer).position();
                 byte chr = byteBuffer.get();
                 if (chr == Constants.SP || chr == Constants.HT) {
                     space = true;
                     request.method().setBytes(byteBuffer.array(), parsingRequestLineStart,
                             pos - parsingRequestLineStart);
                 } else if (!HttpParser.isToken(chr)) {
-                    byteBuffer.position(byteBuffer.position() - 1);
+                    ((Buffer) byteBuffer).position(((Buffer) byteBuffer).position() - 1);
                     throw new IllegalArgumentException(sm.getString("iib.invalidmethod"));
                 }
             }
@@ -433,17 +434,17 @@ public class Http11InputBuffer implement
             boolean space = true;
             while (space) {
                 // Read new bytes if needed
-                if (byteBuffer.position() >= byteBuffer.limit()) {
+                if (((Buffer) byteBuffer).position() >= ((Buffer) byteBuffer).limit()) {
                     if (!fill(false)) // request line parsing
                         return false;
                 }
                 byte chr = byteBuffer.get();
                 if (!(chr == Constants.SP || chr == Constants.HT)) {
                     space = false;
-                    byteBuffer.position(byteBuffer.position() - 1);
+                    ((Buffer) byteBuffer).position(((Buffer) byteBuffer).position() - 1);
                 }
             }
-            parsingRequestLineStart = byteBuffer.position();
+            parsingRequestLineStart = ((Buffer) byteBuffer).position();
             parsingRequestLinePhase = 4;
         }
         if (parsingRequestLinePhase == 4) {
@@ -456,11 +457,11 @@ public class Http11InputBuffer implement
             boolean space = false;
             while (!space) {
                 // Read new bytes if needed
-                if (byteBuffer.position() >= byteBuffer.limit()) {
+                if (((Buffer) byteBuffer).position() >= ((Buffer) byteBuffer).limit()) {
                     if (!fill(false)) // request line parsing
                         return false;
                 }
-                int pos = byteBuffer.position();
+                int pos = ((Buffer) byteBuffer).position();
                 byte chr = byteBuffer.get();
                 if (chr == Constants.SP || chr == Constants.HT) {
                     space = true;
@@ -492,17 +493,17 @@ public class Http11InputBuffer implement
             boolean space = true;
             while (space) {
                 // Read new bytes if needed
-                if (byteBuffer.position() >= byteBuffer.limit()) {
+                if (((Buffer) byteBuffer).position() >= ((Buffer) byteBuffer).limit()) {
                     if (!fill(false)) // request line parsing
                         return false;
                 }
                 byte chr = byteBuffer.get();
                 if (!(chr == Constants.SP || chr == Constants.HT)) {
                     space = false;
-                    byteBuffer.position(byteBuffer.position() - 1);
+                    ((Buffer) byteBuffer).position(((Buffer) byteBuffer).position() - 1);
                 }
             }
-            parsingRequestLineStart = byteBuffer.position();
+            parsingRequestLineStart = ((Buffer) byteBuffer).position();
             parsingRequestLinePhase = 6;
 
             // Mark the current buffer position
@@ -515,12 +516,12 @@ public class Http11InputBuffer implement
             //
             while (!parsingRequestLineEol) {
                 // Read new bytes if needed
-                if (byteBuffer.position() >= byteBuffer.limit()) {
+                if (((Buffer) byteBuffer).position() >= ((Buffer) byteBuffer).limit()) {
                     if (!fill(false)) // request line parsing
                         return false;
                 }
 
-                int pos = byteBuffer.position();
+                int pos = ((Buffer) byteBuffer).position();
                 byte chr = byteBuffer.get();
                 if (chr == Constants.CR) {
                     end = pos;
@@ -571,13 +572,13 @@ public class Http11InputBuffer implement
             // limitation to enforce the meaning of headerBufferSize
             // From the way how buf is allocated and how blank lines are being
             // read, it should be enough to check (1) only.
-            if (byteBuffer.position() > headerBufferSize || byteBuffer.capacity() - byteBuffer.position() < socketReadBufferSize) {
+            if (((Buffer) byteBuffer).position() > headerBufferSize || byteBuffer.capacity() - ((Buffer) byteBuffer).position() < socketReadBufferSize) {
                 throw new IllegalArgumentException(sm.getString("iib.requestheadertoolarge.error"));
             }
         } while (status == HeaderParseStatus.HAVE_MORE_HEADERS);
         if (status == HeaderParseStatus.DONE) {
             parsingHeader = false;
-            end = byteBuffer.position();
+            end = ((Buffer) byteBuffer).position();
             return true;
         } else {
             return false;
@@ -599,7 +600,7 @@ public class Http11InputBuffer implement
 
         if (swallowInput && (lastActiveFilter != -1)) {
             int extraBytes = (int) activeFilters[lastActiveFilter].end();
-            byteBuffer.position(byteBuffer.position() - extraBytes);
+            ((Buffer) byteBuffer).position(((Buffer) byteBuffer).position() - extraBytes);
         }
     }
 
@@ -641,7 +642,7 @@ public class Http11InputBuffer implement
      * faking non-blocking reads with the blocking IO connector.
      */
     boolean isFinished() {
-        if (byteBuffer.limit() > byteBuffer.position()) {
+        if (((Buffer) byteBuffer).limit() > ((Buffer) byteBuffer).position()) {
             // Data to read in the buffer so not finished
             return false;
         }
@@ -669,7 +670,7 @@ public class Http11InputBuffer implement
     ByteBuffer getLeftover() {
         int available = byteBuffer.remaining();
         if (available > 0) {
-            return ByteBuffer.wrap(byteBuffer.array(), byteBuffer.position(), available);
+            return ByteBuffer.wrap(byteBuffer.array(), ((Buffer) byteBuffer).position(), available);
         } else {
             return null;
         }
@@ -685,7 +686,7 @@ public class Http11InputBuffer implement
                 wrapper.getSocketBufferHandler().getReadBuffer().capacity();
         if (byteBuffer == null || byteBuffer.capacity() < bufLength) {
             byteBuffer = ByteBuffer.allocate(bufLength);
-            byteBuffer.position(0).limit(0);
+            ((Buffer) byteBuffer).position(0).limit(0);
         }
     }
 
@@ -702,20 +703,20 @@ public class Http11InputBuffer implement
     private boolean fill(boolean block) throws IOException {
 
         if (parsingHeader) {
-            if (byteBuffer.limit() >= headerBufferSize) {
+            if (((Buffer) byteBuffer).limit() >= headerBufferSize) {
                 throw new IllegalArgumentException(sm.getString("iib.requestheadertoolarge.error"));
             }
         } else {
-            byteBuffer.limit(end).position(end);
+            ((Buffer) byteBuffer).limit(end).position(end);
         }
 
-        byteBuffer.mark();
-        if (byteBuffer.position() < byteBuffer.limit()) {
-            byteBuffer.position(byteBuffer.limit());
+        ((Buffer) byteBuffer).mark();
+        if (((Buffer) byteBuffer).position() < ((Buffer) byteBuffer).limit()) {
+            ((Buffer) byteBuffer).position(((Buffer) byteBuffer).limit());
         }
-        byteBuffer.limit(byteBuffer.capacity());
+        ((Buffer) byteBuffer).limit(byteBuffer.capacity());
         int nRead = wrapper.read(block, byteBuffer);
-        byteBuffer.limit(byteBuffer.position()).reset();
+        ((Buffer) byteBuffer).limit(((Buffer) byteBuffer).position()).reset();
         if (nRead > 0) {
             return true;
         } else if (nRead == -1) {
@@ -743,7 +744,7 @@ public class Http11InputBuffer implement
         while (headerParsePos == HeaderParsePosition.HEADER_START) {
 
             // Read new bytes if needed
-            if (byteBuffer.position() >= byteBuffer.limit()) {
+            if (((Buffer) byteBuffer).position() >= ((Buffer) byteBuffer).limit()) {
                 if (!fill(false)) {// parse header
                     headerParsePos = HeaderParsePosition.HEADER_START;
                     return HeaderParseStatus.NEED_MORE_DATA;
@@ -757,7 +758,7 @@ public class Http11InputBuffer implement
             } else if (chr == Constants.LF) {
                 return HeaderParseStatus.DONE;
             } else {
-                byteBuffer.position(byteBuffer.position() - 1);
+                ((Buffer) byteBuffer).position(((Buffer) byteBuffer).position() - 1);
                 break;
             }
 
@@ -765,7 +766,7 @@ public class Http11InputBuffer implement
 
         if (headerParsePos == HeaderParsePosition.HEADER_START) {
             // Mark the current buffer position
-            headerData.start = byteBuffer.position();
+            headerData.start = ((Buffer) byteBuffer).position();
             headerParsePos = HeaderParsePosition.HEADER_NAME;
         }
 
@@ -777,19 +778,19 @@ public class Http11InputBuffer implement
         while (headerParsePos == HeaderParsePosition.HEADER_NAME) {
 
             // Read new bytes if needed
-            if (byteBuffer.position() >= byteBuffer.limit()) {
+            if (((Buffer) byteBuffer).position() >= ((Buffer) byteBuffer).limit()) {
                 if (!fill(false)) { // parse header
                     return HeaderParseStatus.NEED_MORE_DATA;
                 }
             }
 
-            int pos = byteBuffer.position();
+            int pos = ((Buffer) byteBuffer).position();
             chr = byteBuffer.get();
             if (chr == Constants.COLON) {
                 headerParsePos = HeaderParsePosition.HEADER_VALUE_START;
                 headerData.headerValue = headers.addValue(byteBuffer.array(), headerData.start,
                         pos - headerData.start);
-                pos = byteBuffer.position();
+                pos = ((Buffer) byteBuffer).position();
                 // Mark the current buffer position
                 headerData.start = pos;
                 headerData.realPos = pos;
@@ -799,7 +800,7 @@ public class Http11InputBuffer implement
                 // Non-token characters are illegal in header names
                 // Parsing continues so the error can be reported in context
                 headerData.lastSignificantChar = pos;
-                byteBuffer.position(byteBuffer.position() - 1);
+                ((Buffer) byteBuffer).position(((Buffer) byteBuffer).position() - 1);
                 // skipLine() will handle the error
                 return skipLine();
             }
@@ -827,7 +828,7 @@ public class Http11InputBuffer implement
                 // Skipping spaces
                 while (true) {
                     // Read new bytes if needed
-                    if (byteBuffer.position() >= byteBuffer.limit()) {
+                    if (((Buffer) byteBuffer).position() >= ((Buffer) byteBuffer).limit()) {
                         if (!fill(false)) {// parse header
                             // HEADER_VALUE_START
                             return HeaderParseStatus.NEED_MORE_DATA;
@@ -837,7 +838,7 @@ public class Http11InputBuffer implement
                     chr = byteBuffer.get();
                     if (!(chr == Constants.SP || chr == Constants.HT)) {
                         headerParsePos = HeaderParsePosition.HEADER_VALUE;
-                        byteBuffer.position(byteBuffer.position() - 1);
+                        ((Buffer) byteBuffer).position(((Buffer) byteBuffer).position() - 1);
                         break;
                     }
                 }
@@ -849,7 +850,7 @@ public class Http11InputBuffer implement
                 while (!eol) {
 
                     // Read new bytes if needed
-                    if (byteBuffer.position() >= byteBuffer.limit()) {
+                    if (((Buffer) byteBuffer).position() >= ((Buffer) byteBuffer).limit()) {
                         if (!fill(false)) {// parse header
                             // HEADER_VALUE
                             return HeaderParseStatus.NEED_MORE_DATA;
@@ -879,14 +880,14 @@ public class Http11InputBuffer implement
                 headerParsePos = HeaderParsePosition.HEADER_MULTI_LINE;
             }
             // Read new bytes if needed
-            if (byteBuffer.position() >= byteBuffer.limit()) {
+            if (((Buffer) byteBuffer).position() >= ((Buffer) byteBuffer).limit()) {
                 if (!fill(false)) {// parse header
                     // HEADER_MULTI_LINE
                     return HeaderParseStatus.NEED_MORE_DATA;
                 }
             }
 
-            chr = byteBuffer.get(byteBuffer.position());
+            chr = byteBuffer.get(((Buffer) byteBuffer).position());
             if (headerParsePos == HeaderParsePosition.HEADER_MULTI_LINE) {
                 if ((chr != Constants.SP) && (chr != Constants.HT)) {
                     headerParsePos = HeaderParsePosition.HEADER_START;
@@ -916,13 +917,13 @@ public class Http11InputBuffer implement
         while (!eol) {
 
             // Read new bytes if needed
-            if (byteBuffer.position() >= byteBuffer.limit()) {
+            if (((Buffer) byteBuffer).position() >= ((Buffer) byteBuffer).limit()) {
                 if (!fill(false)) {
                     return HeaderParseStatus.NEED_MORE_DATA;
                 }
             }
 
-            int pos = byteBuffer.position();
+            int pos = ((Buffer) byteBuffer).position();
             byte chr = byteBuffer.get();
             if (chr == Constants.CR) {
                 // Skip
@@ -1049,7 +1050,7 @@ public class Http11InputBuffer implement
         @Override
         public int doRead(ByteChunk chunk) throws IOException {
 
-            if (byteBuffer.position() >= byteBuffer.limit()) {
+            if (((Buffer) byteBuffer).position() >= ((Buffer) byteBuffer).limit()) {
                 // The application is reading the HTTP request body which is
                 // always a blocking operation.
                 if (!fill(true))
@@ -1057,8 +1058,8 @@ public class Http11InputBuffer implement
             }
 
             int length = byteBuffer.remaining();
-            chunk.setBytes(byteBuffer.array(), byteBuffer.position(), length);
-            byteBuffer.position(byteBuffer.limit());
+            chunk.setBytes(byteBuffer.array(), ((Buffer) byteBuffer).position(), length);
+            ((Buffer) byteBuffer).position(((Buffer) byteBuffer).limit());
 
             return length;
         }
@@ -1066,7 +1067,7 @@ public class Http11InputBuffer implement
         @Override
         public int doRead(ApplicationBufferHandler handler) throws IOException {
 
-            if (byteBuffer.position() >= byteBuffer.limit()) {
+            if (((Buffer) byteBuffer).position() >= ((Buffer) byteBuffer).limit()) {
                 // The application is reading the HTTP request body which is
                 // always a blocking operation.
                 if (!fill(true))
@@ -1075,7 +1076,7 @@ public class Http11InputBuffer implement
 
             int length = byteBuffer.remaining();
             handler.setByteBuffer(byteBuffer.duplicate());
-            byteBuffer.position(byteBuffer.limit());
+            ((Buffer) byteBuffer).position(((Buffer) byteBuffer).limit());
 
             return length;
         }
@@ -1097,12 +1098,12 @@ public class Http11InputBuffer implement
     @Override
     public void expand(int size) {
         if (byteBuffer.capacity() >= size) {
-            byteBuffer.limit(size);
+            ((Buffer) byteBuffer).limit(size);
         }
         ByteBuffer temp = ByteBuffer.allocate(size);
         temp.put(byteBuffer);
         byteBuffer = temp;
-        byteBuffer.mark();
+        ((Buffer) byteBuffer).mark();
         temp = null;
     }
 }
--- a/java/org/apache/coyote/http11/filters/BufferedInputFilter.java
+++ b/java/org/apache/coyote/http11/filters/BufferedInputFilter.java
@@ -19,6 +19,7 @@ package org.apache.coyote.http11.filters
 
 import java.io.IOException;
 import java.nio.BufferOverflowException;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 
@@ -68,7 +69,7 @@ public class BufferedInputFilter impleme
     public void setLimit(int limit) {
         if (buffered == null) {
             buffered = ByteBuffer.allocate(limit);
-            buffered.flip();
+            ((Buffer) buffered).flip();
         }
     }
 
@@ -84,9 +85,9 @@ public class BufferedInputFilter impleme
         // save off the Request body
         try {
             while (buffer.doRead(this) >= 0) {
-                buffered.mark().position(buffered.limit()).limit(buffered.capacity());
+                ((Buffer) buffered).mark().position(((Buffer) buffered).limit()).limit(buffered.capacity());
                 buffered.put(tempRead);
-                buffered.limit(buffered.position()).reset();
+                ((Buffer) buffered).limit(((Buffer) buffered).position()).reset();
                 tempRead = null;
             }
         } catch(IOException | BufferOverflowException ioe) {
@@ -109,7 +110,7 @@ public class BufferedInputFilter impleme
             return -1;
         }
 
-        chunk.setBytes(buffered.array(), buffered.arrayOffset() + buffered.position(),
+        chunk.setBytes(buffered.array(), buffered.arrayOffset() + ((Buffer) buffered).position(),
                 buffered.remaining());
         hasRead = true;
         return chunk.getLength();
@@ -140,7 +141,7 @@ public class BufferedInputFilter impleme
             if (buffered.capacity() > 65536) {
                 buffered = null;
             } else {
-                buffered.position(0).limit(0);
+                ((Buffer) buffered).position(0).limit(0);
             }
         }
         hasRead = false;
--- a/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java
+++ b/java/org/apache/coyote/http11/filters/ChunkedInputFilter.java
@@ -18,6 +18,7 @@ package org.apache.coyote.http11.filters
 
 import java.io.EOFException;
 import java.io.IOException;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 import java.util.Locale;
@@ -178,7 +179,7 @@ public class ChunkedInputFilter implemen
 
         int result = 0;
 
-        if (readChunk == null || readChunk.position() >= readChunk.limit()) {
+        if (readChunk == null || ((Buffer) readChunk).position() >= ((Buffer) readChunk).limit()) {
             if (readBytes() < 0) {
                 throwIOException(sm.getString("chunkedInputFilter.eos"));
             }
@@ -187,15 +188,15 @@ public class ChunkedInputFilter implemen
         if (remaining > readChunk.remaining()) {
             result = readChunk.remaining();
             remaining = remaining - result;
-            chunk.setBytes(readChunk.array(), readChunk.arrayOffset() + readChunk.position(), result);
-            readChunk.position(readChunk.limit());
+            chunk.setBytes(readChunk.array(), readChunk.arrayOffset() + ((Buffer) readChunk).position(), result);
+            ((Buffer) readChunk).position(((Buffer) readChunk).limit());
         } else {
             result = remaining;
-            chunk.setBytes(readChunk.array(), readChunk.arrayOffset() + readChunk.position(), remaining);
-            readChunk.position(readChunk.position() + remaining);
+            chunk.setBytes(readChunk.array(), readChunk.arrayOffset() + ((Buffer) readChunk).position(), remaining);
+            ((Buffer) readChunk).position(((Buffer) readChunk).position() + remaining);
             remaining = 0;
             //we need a CRLF
-            if ((readChunk.position() + 1) >= readChunk.limit()) {
+            if ((((Buffer) readChunk).position() + 1) >= ((Buffer) readChunk).limit()) {
                 //if we call parseCRLF we overrun the buffer here
                 //so we defer it to the next call BZ 11117
                 needCRLFParse = true;
@@ -232,7 +233,7 @@ public class ChunkedInputFilter implemen
 
         int result = 0;
 
-        if (readChunk == null || readChunk.position() >= readChunk.limit()) {
+        if (readChunk == null || ((Buffer) readChunk).position() >= ((Buffer) readChunk).limit()) {
             if (readBytes() < 0) {
                 throwIOException(sm.getString("chunkedInputFilter.eos"));
             }
@@ -244,17 +245,17 @@ public class ChunkedInputFilter implemen
             if (readChunk != handler.getByteBuffer()) {
                 handler.setByteBuffer(readChunk.duplicate());
             }
-            readChunk.position(readChunk.limit());
+            ((Buffer) readChunk).position(((Buffer) readChunk).limit());
         } else {
             result = remaining;
             if (readChunk != handler.getByteBuffer()) {
                 handler.setByteBuffer(readChunk.duplicate());
-                handler.getByteBuffer().limit(readChunk.position() + remaining);
+                ((Buffer) handler.getByteBuffer()).limit(((Buffer) readChunk).position() + remaining);
             }
-            readChunk.position(readChunk.position() + remaining);
+            ((Buffer) readChunk).position(((Buffer) readChunk).position() + remaining);
             remaining = 0;
             //we need a CRLF
-            if ((readChunk.position() + 1) >= readChunk.limit()) {
+            if ((((Buffer) readChunk).position() + 1) >= ((Buffer) readChunk).limit()) {
                 //if we call parseCRLF we overrun the buffer here
                 //so we defer it to the next call BZ 11117
                 needCRLFParse = true;
@@ -323,7 +324,7 @@ public class ChunkedInputFilter implemen
     public void recycle() {
         remaining = 0;
         if (readChunk != null) {
-            readChunk.position(0).limit(0);
+            ((Buffer) readChunk).position(0).limit(0);
         }
         endChunk = false;
         needCRLFParse = false;
@@ -385,12 +386,12 @@ public class ChunkedInputFilter implemen
 
         while (!eol) {
 
-            if (readChunk == null || readChunk.position() >= readChunk.limit()) {
+            if (readChunk == null || ((Buffer) readChunk).position() >= ((Buffer) readChunk).limit()) {
                 if (readBytes() <= 0)
                     return false;
             }
 
-            byte chr = readChunk.get(readChunk.position());
+            byte chr = readChunk.get(((Buffer) readChunk).position());
             if (chr == Constants.CR || chr == Constants.LF) {
                 parseCRLF(false);
                 eol = true;
@@ -423,7 +424,7 @@ public class ChunkedInputFilter implemen
 
             // Parsing the CRLF increments pos
             if (!eol) {
-                readChunk.position(readChunk.position() + 1);
+                ((Buffer) readChunk).position(((Buffer) readChunk).position() + 1);
             }
         }
 
@@ -454,13 +455,13 @@ public class ChunkedInputFilter implemen
         boolean crfound = false;
 
         while (!eol) {
-            if (readChunk == null || readChunk.position() >= readChunk.limit()) {
+            if (readChunk == null || ((Buffer) readChunk).position() >= ((Buffer) readChunk).limit()) {
                 if (readBytes() <= 0) {
                     throwIOException(sm.getString("chunkedInputFilter.invalidCrlfNoData"));
                 }
             }
 
-            byte chr = readChunk.get(readChunk.position());
+            byte chr = readChunk.get(((Buffer) readChunk).position());
             if (chr == Constants.CR) {
                 if (crfound) {
                     throwIOException(sm.getString("chunkedInputFilter.invalidCrlfCRCR"));
@@ -475,7 +476,7 @@ public class ChunkedInputFilter implemen
                 throwIOException(sm.getString("chunkedInputFilter.invalidCrlf"));
             }
 
-            readChunk.position(readChunk.position() + 1);
+            ((Buffer) readChunk).position(((Buffer) readChunk).position() + 1);
         }
     }
 
@@ -499,14 +500,14 @@ public class ChunkedInputFilter implemen
         byte chr = 0;
 
         // Read new bytes if needed
-        if (readChunk == null || readChunk.position() >= readChunk.limit()) {
+        if (readChunk == null || ((Buffer) readChunk).position() >= ((Buffer) readChunk).limit()) {
             if (readBytes() <0) {
                throwEOFException(sm.getString("chunkedInputFilter.eosTrailer"));
             }
         }
 
         // readBytes() above will set readChunk unless it returns a value < 0
-        chr = readChunk.get(readChunk.position());
+        chr = readChunk.get(((Buffer) readChunk).position());
 
         // CRLF terminates the request
         if (chr == Constants.CR || chr == Constants.LF) {
@@ -526,14 +527,14 @@ public class ChunkedInputFilter implemen
         while (!colon) {
 
             // Read new bytes if needed
-            if (readChunk == null || readChunk.position() >= readChunk.limit()) {
+            if (readChunk == null || ((Buffer) readChunk).position() >= ((Buffer) readChunk).limit()) {
                 if (readBytes() <0) {
                     throwEOFException(sm.getString("chunkedInputFilter.eosTrailer"));
                 }
             }
 
             // readBytes() above will set readChunk unless it returns a value < 0
-            chr = readChunk.get(readChunk.position());
+            chr = readChunk.get(((Buffer) readChunk).position());
             if ((chr >= Constants.A) && (chr <= Constants.Z)) {
                 chr = (byte) (chr - Constants.LC_OFFSET);
             }
@@ -544,7 +545,7 @@ public class ChunkedInputFilter implemen
                 trailingHeaders.append(chr);
             }
 
-            readChunk.position(readChunk.position() + 1);
+            ((Buffer) readChunk).position(((Buffer) readChunk).position() + 1);
 
         }
         int colonPos = trailingHeaders.getEnd();
@@ -565,15 +566,15 @@ public class ChunkedInputFilter implemen
             while (space) {
 
                 // Read new bytes if needed
-                if (readChunk == null || readChunk.position() >= readChunk.limit()) {
+                if (readChunk == null || ((Buffer) readChunk).position() >= ((Buffer) readChunk).limit()) {
                     if (readBytes() <0) {
                         throwEOFException(sm.getString("chunkedInputFilter.eosTrailer"));
                     }
                 }
 
-                chr = readChunk.get(readChunk.position());
+                chr = readChunk.get(((Buffer) readChunk).position());
                 if ((chr == Constants.SP) || (chr == Constants.HT)) {
-                    readChunk.position(readChunk.position() + 1);
+                    ((Buffer) readChunk).position(((Buffer) readChunk).position() + 1);
                     // If we swallow whitespace, make sure it counts towards the
                     // limit placed on trailing header size
                     int newlimit = trailingHeaders.getLimit() -1;
@@ -591,13 +592,13 @@ public class ChunkedInputFilter implemen
             while (!eol) {
 
                 // Read new bytes if needed
-                if (readChunk == null || readChunk.position() >= readChunk.limit()) {
+                if (readChunk == null || ((Buffer) readChunk).position() >= ((Buffer) readChunk).limit()) {
                     if (readBytes() <0) {
                         throwEOFException(sm.getString("chunkedInputFilter.eosTrailer"));
                     }
                 }
 
-                chr = readChunk.get(readChunk.position());
+                chr = readChunk.get(((Buffer) readChunk).position());
                 if (chr == Constants.CR || chr == Constants.LF) {
                     parseCRLF(true);
                     eol = true;
@@ -609,7 +610,7 @@ public class ChunkedInputFilter implemen
                 }
 
                 if (!eol) {
-                    readChunk.position(readChunk.position() + 1);
+                    ((Buffer) readChunk).position(((Buffer) readChunk).position() + 1);
                 }
             }
 
@@ -617,13 +618,13 @@ public class ChunkedInputFilter implemen
             // is a LWS, then it's a multiline header
 
             // Read new bytes if needed
-            if (readChunk == null || readChunk.position() >= readChunk.limit()) {
+            if (readChunk == null || ((Buffer) readChunk).position() >= ((Buffer) readChunk).limit()) {
                 if (readBytes() <0) {
                     throwEOFException(sm.getString("chunkedInputFilter.eosTrailer"));
                 }
             }
 
-            chr = readChunk.get(readChunk.position());
+            chr = readChunk.get(((Buffer) readChunk).position());
             if ((chr != Constants.SP) && (chr != Constants.HT)) {
                 validLine = false;
             } else {
--- a/java/org/apache/coyote/http11/filters/ChunkedOutputFilter.java
+++ b/java/org/apache/coyote/http11/filters/ChunkedOutputFilter.java
@@ -18,6 +18,7 @@
 package org.apache.coyote.http11.filters;
 
 import java.io.IOException;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 
 import org.apache.coyote.Response;
@@ -93,12 +94,12 @@ public class ChunkedOutputFilter impleme
 
         int pos = calculateChunkHeader(result);
 
-        chunkHeader.position(pos + 1).limit(chunkHeader.position() + 9 - pos);
+        ((Buffer) chunkHeader).position(pos + 1).limit(((Buffer) chunkHeader).position() + 9 - pos);
         buffer.doWrite(chunkHeader);
 
         buffer.doWrite(chunk);
 
-        chunkHeader.position(8).limit(10);
+        ((Buffer) chunkHeader).position(8).limit(10);
         buffer.doWrite(chunkHeader);
 
         return result;
@@ -117,12 +118,12 @@ public class ChunkedOutputFilter impleme
 
         int pos = calculateChunkHeader(result);
 
-        chunkHeader.position(pos + 1).limit(chunkHeader.position() + 9 - pos);
+        ((Buffer) chunkHeader).position(pos + 1).limit(((Buffer) chunkHeader).position() + 9 - pos);
         buffer.doWrite(chunkHeader);
 
         buffer.doWrite(chunk);
 
-        chunkHeader.position(8).limit(10);
+        ((Buffer) chunkHeader).position(8).limit(10);
         buffer.doWrite(chunkHeader);
 
         return result;
@@ -174,7 +175,7 @@ public class ChunkedOutputFilter impleme
     public void end() throws IOException {
         // Write end chunk
         buffer.doWrite(endChunk);
-        endChunk.position(0).limit(endChunk.capacity());
+        ((Buffer) endChunk).position(0).limit(endChunk.capacity());
 
         buffer.end();
     }
--- a/java/org/apache/coyote/http11/filters/GzipOutputFilter.java
+++ b/java/org/apache/coyote/http11/filters/GzipOutputFilter.java
@@ -18,6 +18,7 @@ package org.apache.coyote.http11.filters
 
 import java.io.IOException;
 import java.io.OutputStream;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.util.zip.GZIPOutputStream;
 
@@ -83,7 +84,7 @@ public class GzipOutputFilter implements
         }
         int len = chunk.remaining();
         if (chunk.hasArray()) {
-            compressionStream.write(chunk.array(), chunk.arrayOffset() + chunk.position(), len);
+            compressionStream.write(chunk.array(), chunk.arrayOffset() + ((Buffer) chunk).position(), len);
         } else {
             byte[] bytes = new byte[len];
             chunk.put(bytes);
--- a/java/org/apache/coyote/http11/filters/IdentityOutputFilter.java
+++ b/java/org/apache/coyote/http11/filters/IdentityOutputFilter.java
@@ -17,6 +17,7 @@
 package org.apache.coyote.http11.filters;
 
 import java.io.IOException;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 
 import org.apache.coyote.Response;
@@ -107,7 +108,7 @@ public class IdentityOutputFilter implem
                     // The chunk is longer than the number of bytes remaining
                     // in the body; changing the chunk length to the number
                     // of bytes remaining
-                    chunk.limit(chunk.position() + (int) remaining);
+                    chunk.limit(((Buffer) chunk).position() + (int) remaining);
                     result = (int) remaining;
                     remaining = 0;
                 } else {
@@ -117,8 +118,8 @@ public class IdentityOutputFilter implem
             } else {
                 // No more bytes left to be written : return -1 and clear the
                 // buffer
-                chunk.position(0);
-                chunk.limit(0);
+                ((Buffer) chunk).position(0);
+                ((Buffer) chunk).limit(0);
                 result = -1;
             }
         } else {
--- a/java/org/apache/coyote/http11/filters/SavedRequestInputFilter.java
+++ b/java/org/apache/coyote/http11/filters/SavedRequestInputFilter.java
@@ -18,6 +18,7 @@
 package org.apache.coyote.http11.filters;
 
 import java.io.IOException;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 
 import org.apache.coyote.InputBuffer;
@@ -76,7 +77,7 @@ public class SavedRequestInputFilter imp
             return -1;
 
         ByteBuffer byteBuffer = handler.getByteBuffer();
-        byteBuffer.position(byteBuffer.limit()).limit(byteBuffer.capacity());
+        ((Buffer) byteBuffer).position(((Buffer) byteBuffer).limit()).limit(byteBuffer.capacity());
         input.substract(byteBuffer);
 
         return byteBuffer.remaining();
--- a/java/org/apache/coyote/http2/HPackHuffman.java
+++ b/java/org/apache/coyote/http2/HPackHuffman.java
@@ -16,6 +16,7 @@
  */
 package org.apache.coyote.http2;
 
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.util.Arrays;
 import java.util.HashSet;
@@ -437,7 +438,7 @@ public class HPackHuffman {
         if (buffer.remaining() <= toEncode.length()) {
             return false;
         }
-        int start = buffer.position();
+        int start = ((Buffer) buffer).position();
         //this sucks, but we need to put the length first
         //and we don't really have any option but to calculate it in advance to make sure we have left enough room
         //so we end up iterating twice
@@ -478,7 +479,7 @@ public class HPackHuffman {
                 int rem = code.length;
                 while (rem > 0) {
                     if (!buffer.hasRemaining()) {
-                        buffer.position(start);
+                        ((Buffer) buffer).position(start);
                         return false;
                     }
                     int remainingInByte = 8 - bytePos;
@@ -499,24 +500,24 @@ public class HPackHuffman {
             }
             if (bytePos == 8) {
                 if (!buffer.hasRemaining()) {
-                    buffer.position(start);
+                    ((Buffer) buffer).position(start);
                     return false;
                 }
                 buffer.put(currentBufferByte);
                 currentBufferByte = 0;
                 bytePos = 0;
             }
-            if (buffer.position() - start > toEncode.length()) {
+            if (((Buffer) buffer).position() - start > toEncode.length()) {
                 //the encoded version is longer than the original
                 //just return false
-                buffer.position(start);
+                ((Buffer) buffer).position(start);
                 return false;
             }
         }
         if (bytePos > 0) {
             //add the EOS bytes if we have not finished on a single byte
             if (!buffer.hasRemaining()) {
-                buffer.position(start);
+                ((Buffer) buffer).position(start);
                 return false;
             }
             buffer.put((byte) (currentBufferByte | ((0xFF) >> bytePos)));
--- a/java/org/apache/coyote/http2/Hpack.java
+++ b/java/org/apache/coyote/http2/Hpack.java
@@ -16,6 +16,7 @@
  */
 package org.apache.coyote.http2;
 
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 
 import org.apache.tomcat.util.res.StringManager;
@@ -148,7 +149,7 @@ final class Hpack {
             return -1;
         }
         int count = 1;
-        int sp = source.position();
+        int sp = ((Buffer) source).position();
         int mask = PREFIX_TABLE[n];
 
         int i = mask & source.get();
@@ -165,7 +166,7 @@ final class Hpack {
                 if (source.remaining() == 0) {
                     //we have run out of data
                     //reset
-                    source.position(sp);
+                    ((Buffer) source).position(sp);
                     return -1;
                 }
                 b = source.get();
@@ -189,7 +190,7 @@ final class Hpack {
      */
     static void encodeInteger(ByteBuffer source, int value, int n) {
         int twoNminus1 = PREFIX_TABLE[n];
-        int pos = source.position() - 1;
+        int pos = ((Buffer) source).position() - 1;
         if (value < twoNminus1) {
             source.put(pos, (byte) (source.get(pos) | value));
         } else {
--- a/java/org/apache/coyote/http2/HpackDecoder.java
+++ b/java/org/apache/coyote/http2/HpackDecoder.java
@@ -16,6 +16,7 @@
  */
 package org.apache.coyote.http2;
 
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 
 import org.apache.tomcat.util.res.StringManager;
@@ -95,14 +96,14 @@ public class HpackDecoder {
      */
     public void decode(ByteBuffer buffer) throws HpackException {
         while (buffer.hasRemaining()) {
-            int originalPos = buffer.position();
+            int originalPos = ((Buffer) buffer).position();
             byte b = buffer.get();
             if ((b & 0b10000000) != 0) {
                 //if the first bit is set it is an indexed header field
-                buffer.position(buffer.position() - 1); //unget the byte
+                ((Buffer) buffer).position(((Buffer) buffer).position() - 1); //unget the byte
                 int index = Hpack.decodeInteger(buffer, 7); //prefix is 7
                 if (index == -1) {
-                    buffer.position(originalPos);
+                    ((Buffer) buffer).position(originalPos);
                     return;
                 } else if(index == 0) {
                     throw new HpackException(
@@ -113,12 +114,12 @@ public class HpackDecoder {
                 //Literal Header Field with Incremental Indexing
                 String headerName = readHeaderName(buffer, 6);
                 if (headerName == null) {
-                    buffer.position(originalPos);
+                    ((Buffer) buffer).position(originalPos);
                     return;
                 }
                 String headerValue = readHpackString(buffer);
                 if (headerValue == null) {
-                    buffer.position(originalPos);
+                    ((Buffer) buffer).position(originalPos);
                     return;
                 }
                 emitHeader(headerName, headerValue);
@@ -127,12 +128,12 @@ public class HpackDecoder {
                 //Literal Header Field without Indexing
                 String headerName = readHeaderName(buffer, 4);
                 if (headerName == null) {
-                    buffer.position(originalPos);
+                    ((Buffer) buffer).position(originalPos);
                     return;
                 }
                 String headerValue = readHpackString(buffer);
                 if (headerValue == null) {
-                    buffer.position(originalPos);
+                    ((Buffer) buffer).position(originalPos);
                     return;
                 }
                 emitHeader(headerName, headerValue);
@@ -140,12 +141,12 @@ public class HpackDecoder {
                 //Literal Header Field never indexed
                 String headerName = readHeaderName(buffer, 4);
                 if (headerName == null) {
-                    buffer.position(originalPos);
+                    ((Buffer) buffer).position(originalPos);
                     return;
                 }
                 String headerValue = readHpackString(buffer);
                 if (headerValue == null) {
-                    buffer.position(originalPos);
+                    ((Buffer) buffer).position(originalPos);
                     return;
                 }
                 emitHeader(headerName, headerValue);
@@ -164,10 +165,10 @@ public class HpackDecoder {
         if (headerCount != 0) {
             throw new HpackException(sm.getString("hpackdecoder.tableSizeUpdateNotAtStart"));
         }
-        buffer.position(buffer.position() - 1); //unget the byte
+        ((Buffer) buffer).position(((Buffer) buffer).position() - 1); //unget the byte
         int size = Hpack.decodeInteger(buffer, 5);
         if (size == -1) {
-            buffer.position(originalPos);
+            ((Buffer) buffer).position(originalPos);
             return false;
         }
         if (size > maxMemorySizeHard) {
@@ -196,7 +197,7 @@ public class HpackDecoder {
     }
 
     private String readHeaderName(ByteBuffer buffer, int prefixLength) throws HpackException {
-        buffer.position(buffer.position() - 1); //unget the byte
+        ((Buffer) buffer).position(((Buffer) buffer).position() - 1); //unget the byte
         int index = Hpack.decodeInteger(buffer, prefixLength);
         if (index == -1) {
             return null;
@@ -211,7 +212,7 @@ public class HpackDecoder {
         if (!buffer.hasRemaining()) {
             return null;
         }
-        byte data = buffer.get(buffer.position());
+        byte data = buffer.get(((Buffer) buffer).position());
 
         int length = Hpack.decodeInteger(buffer, 7);
         if (buffer.remaining() < length) {
--- a/java/org/apache/coyote/http2/Http2UpgradeHandler.java
+++ b/java/org/apache/coyote/http2/Http2UpgradeHandler.java
@@ -18,6 +18,7 @@ package org.apache.coyote.http2;
 
 import java.io.EOFException;
 import java.io.IOException;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 import java.util.Collections;
@@ -560,9 +561,9 @@ public class Http2UpgradeHandler extends
                     payload.put(pushedStreamIdBytes);
                 }
                 state = getHpackEncoder().encode(mimeHeaders, payload);
-                payload.flip();
-                if (state == State.COMPLETE || payload.limit() > 0) {
-                    ByteUtil.setThreeBytes(header, 0, payload.limit());
+                ((Buffer) payload).flip();
+                if (state == State.COMPLETE || ((Buffer) payload).limit() > 0) {
+                    ByteUtil.setThreeBytes(header, 0, ((Buffer) payload).limit());
                     if (first) {
                         first = false;
                         if (pushedStreamIdBytes == null) {
@@ -580,7 +581,7 @@ public class Http2UpgradeHandler extends
                         header[4] += FLAG_END_OF_HEADERS;
                     }
                     if (log.isDebugEnabled()) {
-                        log.debug(payload.limit() + " bytes");
+                        log.debug(((Buffer) payload).limit() + " bytes");
                     }
                     ByteUtil.set31Bits(header, 5, stream.getIdentifier().intValue());
                     try {
@@ -590,7 +591,7 @@ public class Http2UpgradeHandler extends
                     } catch (IOException ioe) {
                         handleAppInitiatedIOException(ioe);
                     }
-                    payload.clear();
+                    ((Buffer) payload).clear();
                 } else if (state == State.UNDERFLOW) {
                     payload = ByteBuffer.allocate(payload.capacity() * 2);
                 }
@@ -631,10 +632,10 @@ public class Http2UpgradeHandler extends
             synchronized (socketWrapper) {
                 try {
                     socketWrapper.write(true, header, 0, header.length);
-                    int orgLimit = data.limit();
-                    data.limit(data.position() + len);
+                    int orgLimit = ((Buffer) data).limit();
+                    ((Buffer) data).limit(((Buffer) data).position() + len);
                     socketWrapper.write(true, data);
-                    data.limit(orgLimit);
+                    ((Buffer) data).limit(orgLimit);
                     socketWrapper.flush(true);
                 } catch (IOException ioe) {
                     handleAppInitiatedIOException(ioe);
@@ -1244,9 +1245,9 @@ public class Http2UpgradeHandler extends
 
     @Override
     public boolean fill(boolean block, ByteBuffer data, int len) throws IOException {
-        boolean result = fill(block, data.array(), data.arrayOffset() + data.position(), len);
+        boolean result = fill(block, data.array(), data.arrayOffset() + ((Buffer) data).position(), len);
         if (result) {
-            data.position(data.position() + len);
+            ((Buffer) data).position(((Buffer) data).position() + len);
         }
         return result;
     }
--- a/java/org/apache/coyote/http2/Stream.java
+++ b/java/org/apache/coyote/http2/Stream.java
@@ -17,6 +17,7 @@
 package org.apache.coyote.http2;
 
 import java.io.IOException;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 import java.security.AccessController;
@@ -700,13 +701,13 @@ public class Stream extends AbstractStre
             if (!coyoteResponse.isCommitted()) {
                 coyoteResponse.sendHeaders();
             }
-            int chunkLimit = chunk.limit();
+            int chunkLimit = ((Buffer) chunk).limit();
             int offset = 0;
             while (chunk.remaining() > 0) {
                 int thisTime = Math.min(buffer.remaining(), chunk.remaining());
-                chunk.limit(chunk.position() + thisTime);
+                ((Buffer) chunk).limit(((Buffer) chunk).position() + thisTime);
                 buffer.put(chunk);
-                chunk.limit(chunkLimit);
+                ((Buffer) chunk).limit(chunkLimit);
                 offset += thisTime;
                 if (chunk.remaining() > 0 && !buffer.hasRemaining()) {
                     // Only flush if we have more data to write and the buffer
@@ -728,10 +729,10 @@ public class Stream extends AbstractStre
                 throws IOException {
             if (log.isDebugEnabled()) {
                 log.debug(sm.getString("stream.outputBuffer.flush.debug", getConnectionId(),
-                        getIdentifier(), Integer.toString(buffer.position()),
+                        getIdentifier(), Integer.toString(((Buffer) buffer).position()),
                         Boolean.toString(writeInProgress), Boolean.toString(closed)));
             }
-            if (buffer.position() == 0) {
+            if (((Buffer) buffer).position() == 0) {
                 if (closed && !endOfStreamSent) {
                     // Handling this special case here is simpler than trying
                     // to modify the following code to handle it.
@@ -740,7 +741,7 @@ public class Stream extends AbstractStre
                 // Buffer is empty. Nothing to do.
                 return false;
             }
-            buffer.flip();
+            ((Buffer) buffer).flip();
             int left = buffer.remaining();
             while (left > 0) {
                 int streamReservation  = reserveWindowSize(left, block);
@@ -759,7 +760,7 @@ public class Stream extends AbstractStre
                     left -= connectionReservation;
                 }
             }
-            buffer.clear();
+            ((Buffer) buffer).clear();
             return false;
         }
 
@@ -855,7 +856,7 @@ public class Stream extends AbstractStre
             // Ensure that only one thread accesses inBuffer at a time
             synchronized (inBuffer) {
                 boolean canRead = false;
-                while (inBuffer.position() == 0 && (canRead = isActive() && !isInputFinished())) {
+                while (((Buffer) inBuffer).position() == 0 && (canRead = isActive() && !isInputFinished())) {
                     // Need to block until some data is written
                     try {
                         if (log.isDebugEnabled()) {
@@ -874,17 +875,17 @@ public class Stream extends AbstractStre
                     }
                 }
 
-                if (inBuffer.position() > 0) {
+                if (((Buffer) inBuffer).position() > 0) {
                     // Data is available in the inBuffer. Copy it to the
                     // outBuffer.
-                    inBuffer.flip();
+                    ((Buffer) inBuffer).flip();
                     written = inBuffer.remaining();
                     if (log.isDebugEnabled()) {
                         log.debug(sm.getString("stream.inputBuffer.copy",
                                 Integer.toString(written)));
                     }
                     inBuffer.get(outBuffer, 0, written);
-                    inBuffer.clear();
+                    ((Buffer) inBuffer).clear();
                 } else if (!canRead) {
                     return -1;
                 } else {
@@ -912,7 +913,7 @@ public class Stream extends AbstractStre
             // Ensure that only one thread accesses inBuffer at a time
             synchronized (inBuffer) {
                 boolean canRead = false;
-                while (inBuffer.position() == 0 && (canRead = isActive() && !isInputFinished())) {
+                while (((Buffer) inBuffer).position() == 0 && (canRead = isActive() && !isInputFinished())) {
                     // Need to block until some data is written
                     try {
                         if (log.isDebugEnabled()) {
@@ -931,17 +932,17 @@ public class Stream extends AbstractStre
                     }
                 }
 
-                if (inBuffer.position() > 0) {
+                if (((Buffer) inBuffer).position() > 0) {
                     // Data is available in the inBuffer. Copy it to the
                     // outBuffer.
-                    inBuffer.flip();
+                    ((Buffer) inBuffer).flip();
                     written = inBuffer.remaining();
                     if (log.isDebugEnabled()) {
                         log.debug(sm.getString("stream.inputBuffer.copy",
                                 Integer.toString(written)));
                     }
                     inBuffer.get(outBuffer, 0, written);
-                    inBuffer.clear();
+                    ((Buffer) inBuffer).clear();
                 } else if (!canRead) {
                     return -1;
                 } else {
@@ -970,7 +971,7 @@ public class Stream extends AbstractStre
 
 
         synchronized boolean isRequestBodyFullyRead() {
-            return (inBuffer == null || inBuffer.position() == 0) && isInputFinished();
+            return (inBuffer == null || ((Buffer) inBuffer).position() == 0) && isInputFinished();
         }
 
 
@@ -978,7 +979,7 @@ public class Stream extends AbstractStre
             if (inBuffer == null) {
                 return 0;
             }
-            return inBuffer.position();
+            return ((Buffer) inBuffer).position();
         }
 
 
--- a/java/org/apache/tomcat/util/buf/B2CConverter.java
+++ b/java/org/apache/tomcat/util/buf/B2CConverter.java
@@ -18,6 +18,7 @@ package org.apache.tomcat.util.buf;
 
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
 import java.nio.charset.Charset;
@@ -143,7 +144,7 @@ public class B2CConverter {
      */
     public void recycle() {
         decoder.reset();
-        leftovers.position(0);
+        ((Buffer) leftovers).position(0);
     }
 
     /**
@@ -162,8 +163,8 @@ public class B2CConverter {
             bb = ByteBuffer.wrap(bc.getBuffer(), bc.getStart(), bc.getLength());
         } else {
             // Initialize the byte buffer
-            bb.limit(bc.getEnd());
-            bb.position(bc.getStart());
+            ((Buffer) bb).limit(bc.getEnd());
+            ((Buffer) bb).position(bc.getStart());
         }
         if ((cb == null) || (cb.array() != cc.getBuffer())) {
             // Create a new char buffer if anything changed
@@ -171,26 +172,26 @@ public class B2CConverter {
                     cc.getBuffer().length - cc.getEnd());
         } else {
             // Initialize the char buffer
-            cb.limit(cc.getBuffer().length);
-            cb.position(cc.getEnd());
+            ((Buffer) cb).limit(cc.getBuffer().length);
+            ((Buffer) cb).position(cc.getEnd());
         }
         CoderResult result = null;
         // Parse leftover if any are present
-        if (leftovers.position() > 0) {
-            int pos = cb.position();
+        if (((Buffer) leftovers).position() > 0) {
+            int pos = ((Buffer) cb).position();
             // Loop until one char is decoded or there is a decoder error
             do {
                 leftovers.put(bc.substractB());
-                leftovers.flip();
+                ((Buffer) leftovers).flip();
                 result = decoder.decode(leftovers, cb, endOfInput);
-                leftovers.position(leftovers.limit());
-                leftovers.limit(leftovers.array().length);
-            } while (result.isUnderflow() && (cb.position() == pos));
+                ((Buffer) leftovers).position(((Buffer) leftovers).limit());
+                ((Buffer) leftovers).limit(leftovers.array().length);
+            } while (result.isUnderflow() && (((Buffer) cb).position() == pos));
             if (result.isError() || result.isMalformed()) {
                 result.throwException();
             }
-            bb.position(bc.getStart());
-            leftovers.position(0);
+            ((Buffer) bb).position(bc.getStart());
+            ((Buffer) leftovers).position(0);
         }
         // Do the decoding and get the results into the byte chunk and the char
         // chunk
@@ -200,16 +201,16 @@ public class B2CConverter {
         } else if (result.isOverflow()) {
             // Propagate current positions to the byte chunk and char chunk, if
             // this continues the char buffer will get resized
-            bc.setOffset(bb.position());
-            cc.setEnd(cb.position());
+            bc.setOffset(((Buffer) bb).position());
+            cc.setEnd(((Buffer) cb).position());
         } else if (result.isUnderflow()) {
             // Propagate current positions to the byte chunk and char chunk
-            bc.setOffset(bb.position());
-            cc.setEnd(cb.position());
+            bc.setOffset(((Buffer) bb).position());
+            cc.setEnd(((Buffer) cb).position());
             // Put leftovers in the leftovers byte buffer
             if (bc.getLength() > 0) {
-                leftovers.limit(leftovers.array().length);
-                leftovers.position(bc.getLength());
+                ((Buffer) leftovers).limit(leftovers.array().length);
+                ((Buffer) leftovers).position(bc.getLength());
                 bc.substract(leftovers.array(), 0, bc.getLength());
             }
         }
@@ -229,24 +230,24 @@ public class B2CConverter {
             throws IOException {
         if ((bb == null) || (bb.array() != bc.array())) {
             // Create a new byte buffer if anything changed
-            bb = ByteBuffer.wrap(bc.array(), bc.arrayOffset() + bc.position(), bc.remaining());
+            bb = ByteBuffer.wrap(bc.array(), bc.arrayOffset() + ((Buffer) bc).position(), bc.remaining());
         } else {
             // Initialize the byte buffer
-            bb.limit(bc.limit());
-            bb.position(bc.position());
+            ((Buffer) bb).limit(((Buffer) bc).limit());
+            ((Buffer) bb).position(((Buffer) bc).position());
         }
         if ((cb == null) || (cb.array() != cc.array())) {
             // Create a new char buffer if anything changed
-            cb = CharBuffer.wrap(cc.array(), cc.limit(), cc.capacity() - cc.limit());
+            cb = CharBuffer.wrap(cc.array(), ((Buffer) cc).limit(), cc.capacity() - ((Buffer) cc).limit());
         } else {
             // Initialize the char buffer
-            cb.limit(cc.capacity());
-            cb.position(cc.limit());
+            ((Buffer) cb).limit(cc.capacity());
+            ((Buffer) cb).position(((Buffer) cc).limit());
         }
         CoderResult result = null;
         // Parse leftover if any are present
-        if (leftovers.position() > 0) {
-            int pos = cb.position();
+        if (((Buffer) leftovers).position() > 0) {
+            int pos = ((Buffer) cb).position();
             // Loop until one char is decoded or there is a decoder error
             do {
                 byte chr;
@@ -257,16 +258,16 @@ public class B2CConverter {
                     chr = bc.get();
                 }
                 leftovers.put(chr);
-                leftovers.flip();
+                ((Buffer) leftovers).flip();
                 result = decoder.decode(leftovers, cb, endOfInput);
-                leftovers.position(leftovers.limit());
-                leftovers.limit(leftovers.array().length);
-            } while (result.isUnderflow() && (cb.position() == pos));
+                ((Buffer) leftovers).position(((Buffer) leftovers).limit());
+                ((Buffer) leftovers).limit(leftovers.array().length);
+            } while (result.isUnderflow() && (((Buffer) cb).position() == pos));
             if (result.isError() || result.isMalformed()) {
                 result.throwException();
             }
-            bb.position(bc.position());
-            leftovers.position(0);
+            ((Buffer) bb).position(((Buffer) bc).position());
+            ((Buffer) leftovers).position(0);
         }
         // Do the decoding and get the results into the byte chunk and the char
         // chunk
@@ -276,16 +277,16 @@ public class B2CConverter {
         } else if (result.isOverflow()) {
             // Propagate current positions to the byte chunk and char chunk, if
             // this continues the char buffer will get resized
-            bc.position(bb.position());
-            cc.limit(cb.position());
+            ((Buffer) bc).position(((Buffer) bb).position());
+            ((Buffer) cc).limit(((Buffer) cb).position());
         } else if (result.isUnderflow()) {
             // Propagate current positions to the byte chunk and char chunk
-            bc.position(bb.position());
-            cc.limit(cb.position());
+            ((Buffer) bc).position(((Buffer) bb).position());
+            ((Buffer) cc).limit(((Buffer) cb).position());
             // Put leftovers in the leftovers byte buffer
             if (bc.remaining() > 0) {
-                leftovers.limit(leftovers.array().length);
-                leftovers.position(bc.remaining());
+                ((Buffer) leftovers).limit(leftovers.array().length);
+                ((Buffer) leftovers).position(bc.remaining());
                 bc.get(leftovers.array(), 0, bc.remaining());
             }
         }
--- a/java/org/apache/tomcat/util/buf/ByteBufferHolder.java
+++ b/java/org/apache/tomcat/util/buf/ByteBufferHolder.java
@@ -16,6 +16,7 @@
  */
 package org.apache.tomcat.util.buf;
 
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.util.concurrent.atomic.AtomicBoolean;
 
@@ -46,10 +47,10 @@ public class ByteBufferHolder {
 
     public boolean flip() {
         if (flipped.compareAndSet(false, true)) {
-            buf.flip();
+            ((Buffer) buf).flip();
             return true;
         } else {
             return false;
         }
     }
-}
\ No newline at end of file
+}
--- a/java/org/apache/tomcat/util/buf/ByteBufferUtils.java
+++ b/java/org/apache/tomcat/util/buf/ByteBufferUtils.java
@@ -19,6 +19,7 @@ package org.apache.tomcat.util.buf;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 
 import org.apache.juli.logging.Log;
@@ -109,7 +110,7 @@ public class ByteBufferUtils {
         }
 
         // Copy data
-        in.flip();
+        ((Buffer) in).flip();
         out.put(in);
 
         if (direct) {
--- a/java/org/apache/tomcat/util/buf/ByteChunk.java
+++ b/java/org/apache/tomcat/util/buf/ByteChunk.java
@@ -19,6 +19,7 @@ package org.apache.tomcat.util.buf;
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
 import java.nio.charset.Charset;
@@ -345,7 +346,7 @@ public final class ByteChunk extends Abs
         // and avoid an extra copy
         if (len == limit && end == start && out != null) {
             out.realWriteBytes(from);
-            from.position(from.limit());
+            ((Buffer) from).position(((Buffer) from).limit());
             return;
         }
         // if we have limit and we're below
@@ -371,17 +372,17 @@ public final class ByteChunk extends Abs
 
         flushBuffer();
 
-        int fromLimit = from.limit();
+        int fromLimit = ((Buffer) from).limit();
         int remain = len - avail;
         avail = limit - end;
         while (remain >= avail) {
-            from.limit(from.position() + avail);
+            ((Buffer) from).limit(((Buffer) from).position() + avail);
             out.realWriteBytes(from);
-            from.position(from.limit());
+            ((Buffer) from).position(((Buffer) from).limit());
             remain = remain - avail;
         }
 
-        from.limit(fromLimit);
+        ((Buffer) from).limit(fromLimit);
         from.get(buff, end, remain);
         end += remain;
     }
@@ -436,8 +437,8 @@ public final class ByteChunk extends Abs
         }
         int n = Math.min(to.remaining(), getLength());
         to.put(buff, start, n);
-        to.limit(to.position());
-        to.position(to.position() - n);
+        ((Buffer) to).limit(((Buffer) to).position());
+        ((Buffer) to).position(((Buffer) to).position() - n);
         start += n;
         return n;
     }
--- a/java/org/apache/tomcat/util/buf/C2BConverter.java
+++ b/java/org/apache/tomcat/util/buf/C2BConverter.java
@@ -17,6 +17,7 @@
 package org.apache.tomcat.util.buf;
 
 import java.io.IOException;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
 import java.nio.charset.Charset;
@@ -51,11 +52,11 @@ public final class C2BConverter {
      */
     public void recycle() {
         encoder.reset();
-        leftovers.position(0);
+        ((Buffer) leftovers).position(0);
     }
 
     public boolean isUndeflow() {
-        return (leftovers.position() > 0);
+        return (((Buffer) leftovers).position() > 0);
     }
 
     /**
@@ -71,34 +72,34 @@ public final class C2BConverter {
             bb = ByteBuffer.wrap(bc.getBuffer(), bc.getEnd(), bc.getBuffer().length - bc.getEnd());
         } else {
             // Initialize the byte buffer
-            bb.limit(bc.getBuffer().length);
-            bb.position(bc.getEnd());
+            ((Buffer) bb).limit(bc.getBuffer().length);
+            ((Buffer) bb).position(bc.getEnd());
         }
         if ((cb == null) || (cb.array() != cc.getBuffer())) {
             // Create a new char buffer if anything changed
             cb = CharBuffer.wrap(cc.getBuffer(), cc.getStart(), cc.getLength());
         } else {
             // Initialize the char buffer
-            cb.limit(cc.getEnd());
-            cb.position(cc.getStart());
+            ((Buffer) cb).limit(cc.getEnd());
+            ((Buffer) cb).position(cc.getStart());
         }
         CoderResult result = null;
         // Parse leftover if any are present
-        if (leftovers.position() > 0) {
-            int pos = bb.position();
+        if (((Buffer) leftovers).position() > 0) {
+            int pos = ((Buffer) bb).position();
             // Loop until one char is encoded or there is a encoder error
             do {
                 leftovers.put((char) cc.substract());
-                leftovers.flip();
+                ((Buffer) leftovers).flip();
                 result = encoder.encode(leftovers, bb, false);
-                leftovers.position(leftovers.limit());
-                leftovers.limit(leftovers.array().length);
-            } while (result.isUnderflow() && (bb.position() == pos));
+                ((Buffer) leftovers).position(((Buffer) leftovers).limit());
+                ((Buffer) leftovers).limit(leftovers.array().length);
+            } while (result.isUnderflow() && (((Buffer) bb).position() == pos));
             if (result.isError() || result.isMalformed()) {
                 result.throwException();
             }
-            cb.position(cc.getStart());
-            leftovers.position(0);
+            ((Buffer) cb).position(cc.getStart());
+            ((Buffer) leftovers).position(0);
         }
         // Do the decoding and get the results into the byte chunk and the char
         // chunk
@@ -107,16 +108,16 @@ public final class C2BConverter {
             result.throwException();
         } else if (result.isOverflow()) {
             // Propagate current positions to the byte chunk and char chunk
-            bc.setEnd(bb.position());
-            cc.setOffset(cb.position());
+            bc.setEnd(((Buffer) bb).position());
+            cc.setOffset(((Buffer) cb).position());
         } else if (result.isUnderflow()) {
             // Propagate current positions to the byte chunk and char chunk
-            bc.setEnd(bb.position());
-            cc.setOffset(cb.position());
+            bc.setEnd(((Buffer) bb).position());
+            cc.setOffset(((Buffer) cb).position());
             // Put leftovers in the leftovers char buffer
             if (cc.getLength() > 0) {
-                leftovers.limit(leftovers.array().length);
-                leftovers.position(cc.getLength());
+                ((Buffer) leftovers).limit(leftovers.array().length);
+                ((Buffer) leftovers).position(cc.getLength());
                 cc.substract(leftovers.array(), 0, cc.getLength());
             }
         }
@@ -132,37 +133,37 @@ public final class C2BConverter {
     public void convert(CharBuffer cc, ByteBuffer bc) throws IOException {
         if ((bb == null) || (bb.array() != bc.array())) {
             // Create a new byte buffer if anything changed
-            bb = ByteBuffer.wrap(bc.array(), bc.limit(), bc.capacity() - bc.limit());
+            bb = ByteBuffer.wrap(bc.array(), ((Buffer) bc).limit(), bc.capacity() - ((Buffer) bc).limit());
         } else {
             // Initialize the byte buffer
-            bb.limit(bc.capacity());
-            bb.position(bc.limit());
+            ((Buffer) bb).limit(bc.capacity());
+            ((Buffer) bb).position(((Buffer) bc).limit());
         }
         if ((cb == null) || (cb.array() != cc.array())) {
             // Create a new char buffer if anything changed
-            cb = CharBuffer.wrap(cc.array(), cc.arrayOffset() + cc.position(), cc.remaining());
+            cb = CharBuffer.wrap(cc.array(), cc.arrayOffset() + ((Buffer) cc).position(), cc.remaining());
         } else {
             // Initialize the char buffer
-            cb.limit(cc.limit());
-            cb.position(cc.position());
+            ((Buffer) cb).limit(((Buffer) cc).limit());
+            ((Buffer) cb).position(((Buffer) cc).position());
         }
         CoderResult result = null;
         // Parse leftover if any are present
-        if (leftovers.position() > 0) {
-            int pos = bb.position();
+        if (((Buffer) leftovers).position() > 0) {
+            int pos = ((Buffer) bb).position();
             // Loop until one char is encoded or there is a encoder error
             do {
                 leftovers.put(cc.get());
-                leftovers.flip();
+                ((Buffer) leftovers).flip();
                 result = encoder.encode(leftovers, bb, false);
-                leftovers.position(leftovers.limit());
-                leftovers.limit(leftovers.array().length);
-            } while (result.isUnderflow() && (bb.position() == pos));
+                ((Buffer) leftovers).position(((Buffer) leftovers).limit());
+                ((Buffer) leftovers).limit(leftovers.array().length);
+            } while (result.isUnderflow() && (((Buffer) bb).position() == pos));
             if (result.isError() || result.isMalformed()) {
                 result.throwException();
             }
-            cb.position(cc.position());
-            leftovers.position(0);
+            ((Buffer) cb).position(((Buffer) cc).position());
+            ((Buffer) leftovers).position(0);
         }
         // Do the decoding and get the results into the byte chunk and the char
         // chunk
@@ -171,16 +172,16 @@ public final class C2BConverter {
             result.throwException();
         } else if (result.isOverflow()) {
             // Propagate current positions to the byte chunk and char chunk
-            bc.limit(bb.position());
-            cc.position(cb.position());
+            ((Buffer) bc).limit(((Buffer) bb).position());
+            ((Buffer) cc).position(((Buffer) cb).position());
         } else if (result.isUnderflow()) {
             // Propagate current positions to the byte chunk and char chunk
-            bc.limit(bb.position());
-            cc.position(cb.position());
+            ((Buffer) bc).limit(((Buffer) bb).position());
+            ((Buffer) cc).position(((Buffer) cb).position());
             // Put leftovers in the leftovers char buffer
             if (cc.remaining() > 0) {
-                leftovers.limit(leftovers.array().length);
-                leftovers.position(cc.remaining());
+                ((Buffer) leftovers).limit(leftovers.array().length);
+                ((Buffer) leftovers).position(cc.remaining());
                 cc.get(leftovers.array(), 0, cc.remaining());
             }
         }
--- a/java/org/apache/tomcat/util/buf/MessageBytes.java
+++ b/java/org/apache/tomcat/util/buf/MessageBytes.java
@@ -18,6 +18,7 @@ package org.apache.tomcat.util.buf;
 
 import java.io.IOException;
 import java.io.Serializable;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.charset.Charset;
 import java.util.Locale;
@@ -242,7 +243,7 @@ public final class MessageBytes implemen
         type=T_BYTES;
         Charset charset = byteC.getCharset();
         ByteBuffer result = charset.encode(strValue);
-        byteC.setBytes(result.array(), result.arrayOffset(), result.limit());
+        byteC.setBytes(result.array(), result.arrayOffset(), ((Buffer) result).limit());
     }
 
     /**
--- a/java/org/apache/tomcat/util/buf/Utf8Decoder.java
+++ b/java/org/apache/tomcat/util/buf/Utf8Decoder.java
@@ -16,6 +16,7 @@
  */
 package org.apache.tomcat.util.buf;
 
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
 import java.nio.charset.CharsetDecoder;
@@ -83,8 +84,8 @@ public class Utf8Decoder extends Charset
 
     private CoderResult decodeNotHasArray(ByteBuffer in, CharBuffer out) {
         int outRemaining = out.remaining();
-        int pos = in.position();
-        int limit = in.limit();
+        int pos = ((Buffer) in).position();
+        int limit = ((Buffer) in).limit();
         try {
             while (pos < limit) {
                 if (outRemaining == 0) {
@@ -140,20 +141,20 @@ public class Utf8Decoder extends Charset
             }
             return CoderResult.UNDERFLOW;
         } finally {
-            in.position(pos);
+            ((Buffer) in).position(pos);
         }
     }
 
 
     private CoderResult decodeHasArray(ByteBuffer in, CharBuffer out) {
         int outRemaining = out.remaining();
-        int pos = in.position();
-        int limit = in.limit();
+        int pos = ((Buffer) in).position();
+        int limit = ((Buffer) in).limit();
         final byte[] bArr = in.array();
         final char[] cArr = out.array();
         final int inIndexLimit = limit + in.arrayOffset();
         int inIndex = pos + in.arrayOffset();
-        int outIndex = out.position() + out.arrayOffset();
+        int outIndex = ((Buffer) out).position() + out.arrayOffset();
         // if someone would change the limit in process,
         // he would face consequences
         for (; inIndex < inIndexLimit && outRemaining > 0; inIndex++) {
@@ -163,8 +164,8 @@ public class Utf8Decoder extends Charset
                 // If first byte is invalid, tail will be set to -1
                 int tail = remainingBytes[jchar];
                 if (tail == -1) {
-                    in.position(inIndex - in.arrayOffset());
-                    out.position(outIndex - out.arrayOffset());
+                    ((Buffer) in).position(inIndex - in.arrayOffset());
+                    ((Buffer) out).position(outIndex - out.arrayOffset());
                     return CoderResult.malformedForLength(1);
                 }
                 // Additional checks to detect invalid sequences ASAP
@@ -175,72 +176,72 @@ public class Utf8Decoder extends Charset
                     // First byte C2..DF, second byte 80..BF
                     if (jchar > 0x41 && jchar < 0x60 &&
                             (bArr[inIndex + 1] & 0xC0) != 0x80) {
-                        in.position(inIndex - in.arrayOffset());
-                        out.position(outIndex - out.arrayOffset());
+                        ((Buffer) in).position(inIndex - in.arrayOffset());
+                        ((Buffer) out).position(outIndex - out.arrayOffset());
                         return CoderResult.malformedForLength(1);
                     }
                     // First byte E0, second byte A0..BF
                     if (jchar == 0x60 && (bArr[inIndex + 1] & 0xE0) != 0xA0) {
-                        in.position(inIndex - in.arrayOffset());
-                        out.position(outIndex - out.arrayOffset());
+                        ((Buffer) in).position(inIndex - in.arrayOffset());
+                        ((Buffer) out).position(outIndex - out.arrayOffset());
                         return CoderResult.malformedForLength(1);
                     }
                     // First byte E1..EC, second byte 80..BF
                     if (jchar > 0x60 && jchar < 0x6D &&
                             (bArr[inIndex + 1] & 0xC0) != 0x80) {
-                        in.position(inIndex - in.arrayOffset());
-                        out.position(outIndex - out.arrayOffset());
+                        ((Buffer) in).position(inIndex - in.arrayOffset());
+                        ((Buffer) out).position(outIndex - out.arrayOffset());
                         return CoderResult.malformedForLength(1);
                     }
                     // First byte ED, second byte 80..9F
                     if (jchar == 0x6D && (bArr[inIndex + 1] & 0xE0) != 0x80) {
-                        in.position(inIndex - in.arrayOffset());
-                        out.position(outIndex - out.arrayOffset());
+                        ((Buffer) in).position(inIndex - in.arrayOffset());
+                        ((Buffer) out).position(outIndex - out.arrayOffset());
                         return CoderResult.malformedForLength(1);
                     }
                     // First byte EE..EF, second byte 80..BF
                     if (jchar > 0x6D && jchar < 0x70 &&
                             (bArr[inIndex + 1] & 0xC0) != 0x80) {
-                        in.position(inIndex - in.arrayOffset());
-                        out.position(outIndex - out.arrayOffset());
+                        ((Buffer) in).position(inIndex - in.arrayOffset());
+                        ((Buffer) out).position(outIndex - out.arrayOffset());
                         return CoderResult.malformedForLength(1);
                     }
                     // First byte F0, second byte 90..BF
                     if (jchar == 0x70 &&
                             ((bArr[inIndex + 1] & 0xFF) < 0x90 ||
                             (bArr[inIndex + 1] & 0xFF) > 0xBF)) {
-                        in.position(inIndex - in.arrayOffset());
-                        out.position(outIndex - out.arrayOffset());
+                        ((Buffer) in).position(inIndex - in.arrayOffset());
+                        ((Buffer) out).position(outIndex - out.arrayOffset());
                         return CoderResult.malformedForLength(1);
                     }
                     // First byte F1..F3, second byte 80..BF
                     if (jchar > 0x70 && jchar < 0x74 &&
                             (bArr[inIndex + 1] & 0xC0) != 0x80) {
-                        in.position(inIndex - in.arrayOffset());
-                        out.position(outIndex - out.arrayOffset());
+                        ((Buffer) in).position(inIndex - in.arrayOffset());
+                        ((Buffer) out).position(outIndex - out.arrayOffset());
                         return CoderResult.malformedForLength(1);
                     }
                     // First byte F4, second byte 80..8F
                     if (jchar == 0x74 &&
                             (bArr[inIndex + 1] & 0xF0) != 0x80) {
-                        in.position(inIndex - in.arrayOffset());
-                        out.position(outIndex - out.arrayOffset());
+                        ((Buffer) in).position(inIndex - in.arrayOffset());
+                        ((Buffer) out).position(outIndex - out.arrayOffset());
                         return CoderResult.malformedForLength(1);
                     }
                 }
                 // Check third byte if present and expected
                 if (tailAvailable > 1 && tail > 1) {
                     if ((bArr[inIndex + 2] & 0xC0) != 0x80) {
-                        in.position(inIndex - in.arrayOffset());
-                        out.position(outIndex - out.arrayOffset());
+                        ((Buffer) in).position(inIndex - in.arrayOffset());
+                        ((Buffer) out).position(outIndex - out.arrayOffset());
                         return CoderResult.malformedForLength(2);
                     }
                 }
                 // Check fourth byte if present and expected
                 if (tailAvailable > 2 && tail > 2) {
                     if ((bArr[inIndex + 3] & 0xC0) != 0x80) {
-                        in.position(inIndex - in.arrayOffset());
-                        out.position(outIndex - out.arrayOffset());
+                        ((Buffer) in).position(inIndex - in.arrayOffset());
+                        ((Buffer) out).position(outIndex - out.arrayOffset());
                         return CoderResult.malformedForLength(3);
                     }
                 }
@@ -250,8 +251,8 @@ public class Utf8Decoder extends Charset
                 for (int i = 0; i < tail; i++) {
                     int nextByte = bArr[inIndex + i + 1] & 0xFF;
                     if ((nextByte & 0xC0) != 0x80) {
-                        in.position(inIndex - in.arrayOffset());
-                        out.position(outIndex - out.arrayOffset());
+                        ((Buffer) in).position(inIndex - in.arrayOffset());
+                        ((Buffer) out).position(outIndex - out.arrayOffset());
                         return CoderResult.malformedForLength(1 + i);
                     }
                     jchar = (jchar << 6) + nextByte;
@@ -259,8 +260,8 @@ public class Utf8Decoder extends Charset
                 jchar -= remainingNumbers[tail];
                 if (jchar < lowerEncodingLimit[tail]) {
                     // Should have been encoded in fewer octets
-                    in.position(inIndex - in.arrayOffset());
-                    out.position(outIndex - out.arrayOffset());
+                    ((Buffer) in).position(inIndex - in.arrayOffset());
+                    ((Buffer) out).position(outIndex - out.arrayOffset());
                     return CoderResult.malformedForLength(1);
                 }
                 inIndex += tail;
@@ -285,8 +286,8 @@ public class Utf8Decoder extends Charset
                 outRemaining -= 2;
             }
         }
-        in.position(inIndex - in.arrayOffset());
-        out.position(outIndex - out.arrayOffset());
+        ((Buffer) in).position(inIndex - in.arrayOffset());
+        ((Buffer) out).position(outIndex - out.arrayOffset());
         return (outRemaining == 0 && inIndex < inIndexLimit) ?
                 CoderResult.OVERFLOW :
                 CoderResult.UNDERFLOW;
--- a/java/org/apache/tomcat/util/buf/Utf8Encoder.java
+++ b/java/org/apache/tomcat/util/buf/Utf8Encoder.java
@@ -16,6 +16,7 @@
  */
 package org.apache.tomcat.util.buf;
 
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
 import java.nio.charset.CharsetEncoder;
@@ -42,22 +43,22 @@ public class Utf8Encoder extends Charset
 
     private CoderResult encodeHasArray(CharBuffer in, ByteBuffer out) {
         int outRemaining = out.remaining();
-        int pos = in.position();
-        int limit = in.limit();
+        int pos = ((Buffer) in).position();
+        int limit = ((Buffer) in).limit();
         byte[] bArr;
         char[] cArr;
         int x = pos;
         bArr = out.array();
         cArr = in.array();
-        int outPos = out.position();
+        int outPos = ((Buffer) out).position();
         int rem = in.remaining();
         for (x = pos; x < pos + rem; x++) {
             int jchar = (cArr[x] & 0xFFFF);
 
             if (jchar <= 0x7F) {
                 if (outRemaining < 1) {
-                    in.position(x);
-                    out.position(outPos);
+                    ((Buffer) in).position(x);
+                    ((Buffer) out).position(outPos);
                     return CoderResult.OVERFLOW;
                 }
                 bArr[outPos++] = (byte) (jchar & 0xFF);
@@ -65,8 +66,8 @@ public class Utf8Encoder extends Charset
             } else if (jchar <= 0x7FF) {
 
                 if (outRemaining < 2) {
-                    in.position(x);
-                    out.position(outPos);
+                    ((Buffer) in).position(x);
+                    ((Buffer) out).position(outPos);
                     return CoderResult.OVERFLOW;
                 }
                 bArr[outPos++] = (byte) (0xC0 + ((jchar >> 6) & 0x1F));
@@ -77,21 +78,21 @@ public class Utf8Encoder extends Charset
 
                 // in has to have one byte more.
                 if (limit <= x + 1) {
-                    in.position(x);
-                    out.position(outPos);
+                    ((Buffer) in).position(x);
+                    ((Buffer) out).position(outPos);
                     return CoderResult.UNDERFLOW;
                 }
 
                 if (outRemaining < 4) {
-                    in.position(x);
-                    out.position(outPos);
+                    ((Buffer) in).position(x);
+                    ((Buffer) out).position(outPos);
                     return CoderResult.OVERFLOW;
                 }
 
                 // The surrogate pair starts with a low-surrogate.
                 if (jchar >= 0xDC00) {
-                    in.position(x);
-                    out.position(outPos);
+                    ((Buffer) in).position(x);
+                    ((Buffer) out).position(outPos);
                     return CoderResult.malformedForLength(1);
                 }
 
@@ -99,8 +100,8 @@ public class Utf8Encoder extends Charset
 
                 // The surrogate pair ends with a high-surrogate.
                 if (jchar2 < 0xDC00) {
-                    in.position(x);
-                    out.position(outPos);
+                    ((Buffer) in).position(x);
+                    ((Buffer) out).position(outPos);
                     return CoderResult.malformedForLength(1);
                 }
 
@@ -121,8 +122,8 @@ public class Utf8Encoder extends Charset
             } else {
 
                 if (outRemaining < 3) {
-                    in.position(x);
-                    out.position(outPos);
+                    ((Buffer) in).position(x);
+                    ((Buffer) out).position(outPos);
                     return CoderResult.OVERFLOW;
                 }
                 bArr[outPos++] = (byte) (0xE0 + ((jchar >> 12) & 0x0F));
@@ -131,8 +132,8 @@ public class Utf8Encoder extends Charset
                 outRemaining -= 3;
             }
             if (outRemaining == 0) {
-                in.position(x + 1);
-                out.position(outPos);
+                ((Buffer) in).position(x + 1);
+                ((Buffer) out).position(outPos);
                 // If both input and output are exhausted, return UNDERFLOW
                 if (x + 1 == limit) {
                     return CoderResult.UNDERFLOW;
@@ -143,16 +144,16 @@ public class Utf8Encoder extends Charset
 
         }
         if (rem != 0) {
-            in.position(x);
-            out.position(outPos);
+            ((Buffer) in).position(x);
+            ((Buffer) out).position(outPos);
         }
         return CoderResult.UNDERFLOW;
     }
 
     private CoderResult encodeNotHasArray(CharBuffer in, ByteBuffer out) {
         int outRemaining = out.remaining();
-        int pos = in.position();
-        int limit = in.limit();
+        int pos = ((Buffer) in).position();
+        int limit = ((Buffer) in).limit();
         try {
             while (pos < limit) {
                 if (outRemaining == 0) {
@@ -228,8 +229,8 @@ public class Utf8Encoder extends Charset
                 pos++;
             }
         } finally {
-            in.position(pos);
+            ((Buffer) in).position(pos);
         }
         return CoderResult.UNDERFLOW;
     }
-}
\ No newline at end of file
+}
--- a/java/org/apache/tomcat/util/net/AprEndpoint.java
+++ b/java/org/apache/tomcat/util/net/AprEndpoint.java
@@ -20,6 +20,7 @@ import java.io.EOFException;
 import java.io.IOException;
 import java.net.InetSocketAddress;
 import java.net.SocketTimeoutException;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
@@ -2414,7 +2415,7 @@ public class AprEndpoint extends Abstrac
             //      SSL and app buffer size settings with NIO & NIO2.
             if (endpoint.isSSLEnabled()) {
                 sslOutputBuffer = ByteBuffer.allocateDirect(SSL_OUTPUT_BUFFER_SIZE);
-                sslOutputBuffer.position(SSL_OUTPUT_BUFFER_SIZE);
+                ((Buffer) sslOutputBuffer).position(SSL_OUTPUT_BUFFER_SIZE);
             } else {
                 sslOutputBuffer = null;
             }
@@ -2468,7 +2469,7 @@ public class AprEndpoint extends Abstrac
             // The socket read buffer capacity is socket.appReadBufSize
             int limit = socketBufferHandler.getReadBuffer().capacity();
             if (to.isDirect() && to.remaining() >= limit) {
-                to.limit(to.position() + limit);
+                ((Buffer) to).limit(((Buffer) to).position() + limit);
                 nRead = fillReadBuffer(block, to);
             } else {
                 // Fill the read buffer as best we can.
@@ -2506,7 +2507,7 @@ public class AprEndpoint extends Abstrac
                     if (block) {
                         Socket.timeoutSet(getSocket().longValue(), getReadTimeout() * 1000);
                     }
-                    result = Socket.recvb(getSocket().longValue(), to, to.position(),
+                    result = Socket.recvb(getSocket().longValue(), to, ((Buffer) to).position(),
                             to.remaining());
                     readDone = true;
                 }
@@ -2528,7 +2529,7 @@ public class AprEndpoint extends Abstrac
                     readLock.lock();
                     try {
                         writeLock.unlock();
-                        result = Socket.recvb(getSocket().longValue(), to, to.position(),
+                        result = Socket.recvb(getSocket().longValue(), to, ((Buffer) to).position(),
                                 to.remaining());
                     } finally {
                         readLock.unlock();
@@ -2543,7 +2544,7 @@ public class AprEndpoint extends Abstrac
             }
 
             if (result > 0) {
-                to.position(to.position() + result);
+                ((Buffer) to).position(((Buffer) to).position() + result);
                 return result;
             } else if (result == 0 || -result == Status.EAGAIN) {
                 return 0;
@@ -2646,9 +2647,9 @@ public class AprEndpoint extends Abstrac
                 while (from.remaining() >= limit) {
                     socketBufferHandler.configureWriteBufferForWrite();
                     transfer(from, writeBuffer);
-                    int newPosition = writeBuffer.position() + limit;
+                    int newPosition = ((Buffer) writeBuffer).position() + limit;
                     doWrite(false);
-                    if (writeBuffer.position() != newPosition) {
+                    if (((Buffer) writeBuffer).position() != newPosition) {
                         // Didn't write the whole amount of data in the last
                         // non-blocking write.
                         // Exit the loop.
@@ -2724,24 +2725,24 @@ public class AprEndpoint extends Abstrac
                 if (getEndpoint().isSSLEnabled()) {
                     if (sslOutputBuffer.remaining() == 0) {
                         // Buffer was fully written last time around
-                        sslOutputBuffer.clear();
+                        ((Buffer) sslOutputBuffer).clear();
                         transfer(from, sslOutputBuffer);
-                        sslOutputBuffer.flip();
+                        ((Buffer) sslOutputBuffer).flip();
                     } else {
                         // Buffer still has data from previous attempt to write
                         // APR + SSL requires that exactly the same parameters are
                         // passed when re-attempting the write
                     }
                     thisTime = Socket.sendb(getSocket().longValue(), sslOutputBuffer,
-                            sslOutputBuffer.position(), sslOutputBuffer.limit());
+                            ((Buffer) sslOutputBuffer).position(), ((Buffer) sslOutputBuffer).limit());
                     if (thisTime > 0) {
-                        sslOutputBuffer.position(sslOutputBuffer.position() + thisTime);
+                        ((Buffer) sslOutputBuffer).position(((Buffer) sslOutputBuffer).position() + thisTime);
                     }
                 } else {
-                    thisTime = Socket.sendb(getSocket().longValue(), from, from.position(),
+                    thisTime = Socket.sendb(getSocket().longValue(), from, ((Buffer) from).position(),
                             from.remaining());
                     if (thisTime > 0) {
-                        from.position(from.position() + thisTime);
+                        ((Buffer) from).position(((Buffer) from).position() + thisTime);
                     }
                 }
                 if (Status.APR_STATUS_IS_EAGAIN(-thisTime)) {
--- a/java/org/apache/tomcat/util/net/Nio2Endpoint.java
+++ b/java/org/apache/tomcat/util/net/Nio2Endpoint.java
@@ -22,6 +22,7 @@ import java.io.IOException;
 import java.net.InetSocketAddress;
 import java.net.SocketAddress;
 import java.net.SocketTimeoutException;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.channels.AsynchronousChannelGroup;
 import java.nio.channels.AsynchronousCloseException;
@@ -573,7 +574,7 @@ public class Nio2Endpoint extends Abstra
                         if (nRead > 0) {
                             getSocket().getBufHandler().configureWriteBufferForRead();
                             if (attachment.length < buffer.remaining()) {
-                                buffer.limit(buffer.limit() - buffer.remaining() + (int) attachment.length);
+                                ((Buffer) buffer).limit(((Buffer) buffer).limit() - buffer.remaining() + (int) attachment.length);
                             }
                             attachment.length -= nRead;
                         } else {
@@ -898,7 +899,7 @@ public class Nio2Endpoint extends Abstra
                 // The socket read buffer capacity is socket.appReadBufSize
                 int limit = socketBufferHandler.getReadBuffer().capacity();
                 if (block && to.remaining() >= limit) {
-                    to.limit(to.position() + limit);
+                    ((Buffer) to).limit(((Buffer) to).position() + limit);
                     nRead = fillReadBuffer(block, to);
                 } else {
                     // Fill the read buffer as best we can.
@@ -1161,7 +1162,7 @@ public class Nio2Endpoint extends Abstra
                         readCompletionHandler);
                 Nio2Endpoint.endInline();
                 if (readPending.availablePermits() == 1) {
-                    nRead = to.position();
+                    nRead = ((Buffer) to).position();
                 }
             }
             return nRead;
--- a/java/org/apache/tomcat/util/net/NioEndpoint.java
+++ b/java/org/apache/tomcat/util/net/NioEndpoint.java
@@ -24,6 +24,7 @@ import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.Socket;
 import java.net.SocketTimeoutException;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.channels.CancelledKeyException;
 import java.nio.channels.FileChannel;
@@ -1186,7 +1187,7 @@ public class NioEndpoint extends Abstrac
             // The socket read buffer capacity is socket.appReadBufSize
             int limit = socketBufferHandler.getReadBuffer().capacity();
             if (to.remaining() >= limit) {
-                to.limit(to.position() + limit);
+                ((Buffer) to).limit(((Buffer) to).position() + limit);
                 nRead = fillReadBuffer(block, to);
                 updateLastRead();
             } else {
--- a/java/org/apache/tomcat/util/net/SecureNio2Channel.java
+++ b/java/org/apache/tomcat/util/net/SecureNio2Channel.java
@@ -18,6 +18,7 @@ package org.apache.tomcat.util.net;
 
 import java.io.EOFException;
 import java.io.IOException;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.channels.AsynchronousSocketChannel;
 import java.nio.channels.CompletionHandler;
@@ -132,7 +133,7 @@ public class SecureNio2Channel extends N
         handshakeComplete = false;
         closed = false;
         closing = false;
-        netInBuffer.clear();
+        ((Buffer) netInBuffer).clear();
     }
 
     @Override
@@ -298,9 +299,9 @@ public class SecureNio2Channel extends N
                         if (handshakeStatus == HandshakeStatus.NEED_TASK)
                             handshakeStatus = tasks();
                     } else if (handshake.getStatus() == Status.BUFFER_UNDERFLOW) {
-                        if (netInBuffer.position() == netInBuffer.limit()) {
+                        if (((Buffer) netInBuffer).position() == ((Buffer) netInBuffer).limit()) {
                             //clear the buffer if we have emptied it out on data
-                            netInBuffer.clear();
+                            ((Buffer) netInBuffer).clear();
                         }
                         //read more data
                         if (async) {
@@ -343,7 +344,7 @@ public class SecureNio2Channel extends N
         // If there is no data to process, trigger a read immediately. This is
         // an optimisation for the typical case so we don't create an
         // SNIExtractor only to discover there is no data to process
-        if (netInBuffer.position() == 0) {
+        if (((Buffer) netInBuffer).position() == 0) {
             sc.read(netInBuffer, socket, handshakeReadCompletionHandler);
             return 1;
         }
@@ -387,9 +388,9 @@ public class SecureNio2Channel extends N
             clientRequestedCiphers = Collections.emptyList();
             break;
         case NON_SECURE:
-            netOutBuffer.clear();
+            ((Buffer) netOutBuffer).clear();
             netOutBuffer.put(TLSClientHelloExtractor.USE_TLS_RESPONSE);
-            netOutBuffer.flip();
+            ((Buffer) netOutBuffer).flip();
             flush();
             throw new IOException(sm.getString("channel.nio.ssl.foundHttp"));
         }
@@ -413,8 +414,8 @@ public class SecureNio2Channel extends N
         netOutBuffer = ByteBufferUtils.expand(netOutBuffer, sslEngine.getSession().getPacketBufferSize());
 
         // Set limit and position to expected values
-        netOutBuffer.position(0);
-        netOutBuffer.limit(0);
+        ((Buffer) netOutBuffer).position(0);
+        ((Buffer) netOutBuffer).limit(0);
 
         // Initiate handshake
         sslEngine.beginHandshake();
@@ -433,15 +434,15 @@ public class SecureNio2Channel extends N
      */
     public void rehandshake() throws IOException {
         //validate the network buffers are empty
-        if (netInBuffer.position() > 0 && netInBuffer.position() < netInBuffer.limit()) throw new IOException(sm.getString("channel.nio.ssl.netInputNotEmpty"));
-        if (netOutBuffer.position() > 0 && netOutBuffer.position() < netOutBuffer.limit()) throw new IOException(sm.getString("channel.nio.ssl.netOutputNotEmpty"));
+        if (((Buffer) netInBuffer).position() > 0 && ((Buffer) netInBuffer).position() < ((Buffer) netInBuffer).limit()) throw new IOException(sm.getString("channel.nio.ssl.netInputNotEmpty"));
+        if (((Buffer) netOutBuffer).position() > 0 && ((Buffer) netOutBuffer).position() < ((Buffer) netOutBuffer).limit()) throw new IOException(sm.getString("channel.nio.ssl.netOutputNotEmpty"));
         if (!getBufHandler().isReadBufferEmpty()) throw new IOException(sm.getString("channel.nio.ssl.appInputNotEmpty"));
         if (!getBufHandler().isWriteBufferEmpty()) throw new IOException(sm.getString("channel.nio.ssl.appOutputNotEmpty"));
 
-        netOutBuffer.position(0);
-        netOutBuffer.limit(0);
-        netInBuffer.position(0);
-        netInBuffer.limit(0);
+        ((Buffer) netOutBuffer).position(0);
+        ((Buffer) netOutBuffer).limit(0);
+        ((Buffer) netInBuffer).position(0);
+        ((Buffer) netInBuffer).limit(0);
         getBufHandler().reset();
 
         handshakeComplete = false;
@@ -490,12 +491,12 @@ public class SecureNio2Channel extends N
     protected SSLEngineResult handshakeWrap() throws IOException {
         //this should never be called with a network buffer that contains data
         //so we can clear it here.
-        netOutBuffer.clear();
+        ((Buffer) netOutBuffer).clear();
         //perform the wrap
         getBufHandler().configureWriteBufferForRead();
         SSLEngineResult result = sslEngine.wrap(getBufHandler().getWriteBuffer(), netOutBuffer);
         //prepare the results to be written
-        netOutBuffer.flip();
+        ((Buffer) netOutBuffer).flip();
         //set the status
         handshakeStatus = result.getHandshakeStatus();
         return result;
@@ -512,7 +513,7 @@ public class SecureNio2Channel extends N
         //loop while we can perform pure SSLEngine data
         do {
             //prepare the buffer with the incoming data
-            netInBuffer.flip();
+            ((Buffer) netInBuffer).flip();
             //call unwrap
             getBufHandler().configureReadBufferForWrite();
             result = sslEngine.unwrap(netInBuffer, getBufHandler().getReadBuffer());
@@ -559,7 +560,7 @@ public class SecureNio2Channel extends N
             throw new IOException(sm.getString("channel.nio.ssl.pendingWriteDuringClose"), e);
         }
         //prep the buffer for the close message
-        netOutBuffer.clear();
+        ((Buffer) netOutBuffer).clear();
         //perform the close, since we called sslEngine.closeOutbound
         SSLEngineResult handshake = sslEngine.wrap(getEmptyBuf(), netOutBuffer);
         //we should be in a close state
@@ -567,7 +568,7 @@ public class SecureNio2Channel extends N
             throw new IOException(sm.getString("channel.nio.ssl.invalidCloseState"));
         }
         //prepare the buffer for writing
-        netOutBuffer.flip();
+        ((Buffer) netOutBuffer).flip();
         //if there is data to be written
         try {
             if (!flush().get(endpoint.getConnectionTimeout(), TimeUnit.MILLISECONDS).booleanValue()) {
@@ -613,7 +614,7 @@ public class SecureNio2Channel extends N
         private Future<Integer> integer;
         private FutureRead(ByteBuffer dst) {
             this.dst = dst;
-            if (unwrapBeforeRead || netInBuffer.position() > 0) {
+            if (unwrapBeforeRead || ((Buffer) netInBuffer).position() > 0) {
                 this.integer = null;
             } else {
                 this.integer = sc.read(netInBuffer);
@@ -634,7 +635,7 @@ public class SecureNio2Channel extends N
         @Override
         public Integer get() throws InterruptedException, ExecutionException {
             try {
-                return (integer == null) ? unwrap(netInBuffer.position(), -1, TimeUnit.MILLISECONDS) : unwrap(integer.get().intValue(), -1, TimeUnit.MILLISECONDS);
+                return (integer == null) ? unwrap(((Buffer) netInBuffer).position(), -1, TimeUnit.MILLISECONDS) : unwrap(integer.get().intValue(), -1, TimeUnit.MILLISECONDS);
             } catch (TimeoutException e) {
                 // Cannot happen: no timeout
                 throw new ExecutionException(e);
@@ -644,7 +645,7 @@ public class SecureNio2Channel extends N
         public Integer get(long timeout, TimeUnit unit)
                 throws InterruptedException, ExecutionException,
                 TimeoutException {
-            return (integer == null) ? unwrap(netInBuffer.position(), timeout, unit) : unwrap(integer.get(timeout, unit).intValue(), timeout, unit);
+            return (integer == null) ? unwrap(((Buffer) netInBuffer).position(), timeout, unit) : unwrap(integer.get(timeout, unit).intValue(), timeout, unit);
         }
         private Integer unwrap(int nRead, long timeout, TimeUnit unit) throws ExecutionException, TimeoutException, InterruptedException {
             //are we in the middle of closing or closed?
@@ -659,7 +660,7 @@ public class SecureNio2Channel extends N
             SSLEngineResult unwrap;
             do {
                 //prepare the buffer
-                netInBuffer.flip();
+                ((Buffer) netInBuffer).flip();
                 //unwrap the data
                 try {
                     unwrap = sslEngine.unwrap(netInBuffer, dst);
@@ -716,7 +717,7 @@ public class SecureNio2Channel extends N
                     // Something else went wrong
                     throw new ExecutionException(new IOException(sm.getString("channel.nio.ssl.unwrapFail", unwrap.getStatus())));
                 }
-            } while (netInBuffer.position() != 0); //continue to unwrapping as long as the input buffer has stuff
+            } while (((Buffer) netInBuffer).position() != 0); //continue to unwrapping as long as the input buffer has stuff
             if (!dst.hasRemaining()) {
                 unwrapBeforeRead = true;
             } else {
@@ -802,10 +803,10 @@ public class SecureNio2Channel extends N
         protected void wrap() {
             try {
                 if (!netOutBuffer.hasRemaining()) {
-                    netOutBuffer.clear();
+                    ((Buffer) netOutBuffer).clear();
                     SSLEngineResult result = sslEngine.wrap(src, netOutBuffer);
                     written = result.bytesConsumed();
-                    netOutBuffer.flip();
+                    ((Buffer) netOutBuffer).flip();
                     if (result.getStatus() == Status.OK) {
                         if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK)
                             tasks();
@@ -857,7 +858,7 @@ public class SecureNio2Channel extends N
                         SSLEngineResult unwrap;
                         do {
                             //prepare the buffer
-                            netInBuffer.flip();
+                            ((Buffer) netInBuffer).flip();
                             //unwrap the data
                             unwrap = sslEngine.unwrap(netInBuffer, dst2);
                             //compact the buffer
@@ -907,7 +908,7 @@ public class SecureNio2Channel extends N
                                 throw new IOException(sm.getString("channel.nio.ssl.unwrapFail", unwrap.getStatus()));
                             }
                         // continue to unwrap as long as the input buffer has stuff
-                        } while (netInBuffer.position() != 0);
+                        } while (((Buffer) netInBuffer).position() != 0);
                         if (!dst2.hasRemaining()) {
                             unwrapBeforeRead = true;
                         } else {
@@ -925,8 +926,8 @@ public class SecureNio2Channel extends N
                 handler.failed(exc, attach);
             }
         };
-        if (unwrapBeforeRead || netInBuffer.position() > 0) {
-            readCompletionHandler.completed(Integer.valueOf(netInBuffer.position()), attachment);
+        if (unwrapBeforeRead || ((Buffer) netInBuffer).position() > 0) {
+            readCompletionHandler.completed(Integer.valueOf(((Buffer) netInBuffer).position()), attachment);
         } else {
             sc.read(netInBuffer, timeout, unit, attachment, readCompletionHandler);
         }
@@ -959,7 +960,7 @@ public class SecureNio2Channel extends N
                         SSLEngineResult unwrap;
                         do {
                             //prepare the buffer
-                            netInBuffer.flip();
+                            ((Buffer) netInBuffer).flip();
                             //unwrap the data
                             unwrap = sslEngine.unwrap(netInBuffer, dsts, offset, length);
                             //compact the buffer
@@ -989,7 +990,7 @@ public class SecureNio2Channel extends N
                                 //in the constructor
                                 throw new IOException(sm.getString("channel.nio.ssl.unwrapFail", unwrap.getStatus()));
                             }
-                        } while (netInBuffer.position() != 0); //continue to unwrapping as long as the input buffer has stuff
+                        } while (((Buffer) netInBuffer).position() != 0); //continue to unwrapping as long as the input buffer has stuff
                         int capacity = 0;
                         final int endOffset = offset + length;
                         for (int i = offset; i < endOffset; i++) {
@@ -1012,8 +1013,8 @@ public class SecureNio2Channel extends N
                 handler.failed(exc, attach);
             }
         };
-        if (unwrapBeforeRead || netInBuffer.position() > 0) {
-            readCompletionHandler.completed(Integer.valueOf(netInBuffer.position()), attachment);
+        if (unwrapBeforeRead || ((Buffer) netInBuffer).position() > 0) {
+            readCompletionHandler.completed(Integer.valueOf(((Buffer) netInBuffer).position()), attachment);
         } else {
             sc.read(netInBuffer, timeout, unit, attachment, readCompletionHandler);
         }
@@ -1029,11 +1030,11 @@ public class SecureNio2Channel extends N
         }
         try {
             // Prepare the output buffer
-            netOutBuffer.clear();
+            ((Buffer) netOutBuffer).clear();
             // Wrap the source data into the internal buffer
             SSLEngineResult result = sslEngine.wrap(src, netOutBuffer);
             final int written = result.bytesConsumed();
-            netOutBuffer.flip();
+            ((Buffer) netOutBuffer).flip();
             if (result.getStatus() == Status.OK) {
                 if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
                     tasks();
@@ -1083,11 +1084,11 @@ public class SecureNio2Channel extends N
         }
         try {
              // Prepare the output buffer
-            netOutBuffer.clear();
+            ((Buffer) netOutBuffer).clear();
             // Wrap the source data into the internal buffer
             SSLEngineResult result = sslEngine.wrap(srcs, offset, length, netOutBuffer);
             final int written = result.bytesConsumed();
-            netOutBuffer.flip();
+            ((Buffer) netOutBuffer).flip();
             if (result.getStatus() == Status.OK) {
                 if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {
                     tasks();
@@ -1139,4 +1140,4 @@ public class SecureNio2Channel extends N
     public ByteBuffer getEmptyBuf() {
         return emptyBuf;
     }
-}
\ No newline at end of file
+}
--- a/java/org/apache/tomcat/util/net/SecureNioChannel.java
+++ b/java/org/apache/tomcat/util/net/SecureNioChannel.java
@@ -19,6 +19,7 @@ package org.apache.tomcat.util.net;
 import java.io.EOFException;
 import java.io.IOException;
 import java.net.SocketTimeoutException;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.channels.SelectionKey;
 import java.nio.channels.Selector;
@@ -94,7 +95,7 @@ public class SecureNioChannel extends Ni
         handshakeComplete = false;
         closed = false;
         closing = false;
-        netInBuffer.clear();
+        ((Buffer) netInBuffer).clear();
     }
 
     @Override
@@ -315,9 +316,9 @@ public class SecureNioChannel extends Ni
             clientRequestedCiphers = Collections.emptyList();
             break;
         case NON_SECURE:
-            netOutBuffer.clear();
+            ((Buffer) netOutBuffer).clear();
             netOutBuffer.put(TLSClientHelloExtractor.USE_TLS_RESPONSE);
-            netOutBuffer.flip();
+            ((Buffer) netOutBuffer).flip();
             flushOutbound();
             throw new IOException(sm.getString("channel.nio.ssl.foundHttp"));
         }
@@ -341,8 +342,8 @@ public class SecureNioChannel extends Ni
         netOutBuffer = ByteBufferUtils.expand(netOutBuffer, sslEngine.getSession().getPacketBufferSize());
 
         // Set limit and position to expected values
-        netOutBuffer.position(0);
-        netOutBuffer.limit(0);
+        ((Buffer) netOutBuffer).position(0);
+        ((Buffer) netOutBuffer).limit(0);
 
         // Initiate handshake
         sslEngine.beginHandshake();
@@ -363,8 +364,8 @@ public class SecureNioChannel extends Ni
     @SuppressWarnings("null") // key cannot be null
     public void rehandshake(long timeout) throws IOException {
         //validate the network buffers are empty
-        if (netInBuffer.position() > 0 && netInBuffer.position()<netInBuffer.limit()) throw new IOException(sm.getString("channel.nio.ssl.netInputNotEmpty"));
-        if (netOutBuffer.position() > 0 && netOutBuffer.position()<netOutBuffer.limit()) throw new IOException(sm.getString("channel.nio.ssl.netOutputNotEmpty"));
+        if (((Buffer) netInBuffer).position() > 0 && ((Buffer) netInBuffer).position()<((Buffer) netInBuffer).limit()) throw new IOException(sm.getString("channel.nio.ssl.netInputNotEmpty"));
+        if (((Buffer) netOutBuffer).position() > 0 && ((Buffer) netOutBuffer).position()<((Buffer) netOutBuffer).limit()) throw new IOException(sm.getString("channel.nio.ssl.netOutputNotEmpty"));
         if (!getBufHandler().isReadBufferEmpty()) throw new IOException(sm.getString("channel.nio.ssl.appInputNotEmpty"));
         if (!getBufHandler().isWriteBufferEmpty()) throw new IOException(sm.getString("channel.nio.ssl.appOutputNotEmpty"));
         handshakeComplete = false;
@@ -434,12 +435,12 @@ public class SecureNioChannel extends Ni
     protected SSLEngineResult handshakeWrap(boolean doWrite) throws IOException {
         //this should never be called with a network buffer that contains data
         //so we can clear it here.
-        netOutBuffer.clear();
+        ((Buffer) netOutBuffer).clear();
         //perform the wrap
         getBufHandler().configureWriteBufferForRead();
         SSLEngineResult result = sslEngine.wrap(getBufHandler().getWriteBuffer(), netOutBuffer);
         //prepare the results to be written
-        netOutBuffer.flip();
+        ((Buffer) netOutBuffer).flip();
         //set the status
         handshakeStatus = result.getHandshakeStatus();
         //optimization, if we do have a writable channel, write it now
@@ -455,9 +456,9 @@ public class SecureNioChannel extends Ni
      */
     protected SSLEngineResult handshakeUnwrap(boolean doread) throws IOException {
 
-        if (netInBuffer.position() == netInBuffer.limit()) {
+        if (((Buffer) netInBuffer).position() == ((Buffer) netInBuffer).limit()) {
             //clear the buffer if we have emptied it out on data
-            netInBuffer.clear();
+            ((Buffer) netInBuffer).clear();
         }
         if ( doread )  {
             //if we have data to read, read it
@@ -469,7 +470,7 @@ public class SecureNioChannel extends Ni
         //loop while we can perform pure SSLEngine data
         do {
             //prepare the buffer with the incoming data
-            netInBuffer.flip();
+            ((Buffer) netInBuffer).flip();
             //call unwrap
             getBufHandler().configureReadBufferForWrite();
             result = sslEngine.unwrap(netInBuffer, getBufHandler().getReadBuffer());
@@ -511,7 +512,7 @@ public class SecureNioChannel extends Ni
             throw new IOException(sm.getString("channel.nio.ssl.remainingDataDuringClose"));
         }
         //prep the buffer for the close message
-        netOutBuffer.clear();
+        ((Buffer) netOutBuffer).clear();
         //perform the close, since we called sslEngine.closeOutbound
         SSLEngineResult handshake = sslEngine.wrap(getEmptyBuf(), netOutBuffer);
         //we should be in a close state
@@ -519,7 +520,7 @@ public class SecureNioChannel extends Ni
             throw new IOException(sm.getString("channel.nio.ssl.invalidCloseState"));
         }
         //prepare the buffer for writing
-        netOutBuffer.flip();
+        ((Buffer) netOutBuffer).flip();
         //if there is data to be written
         flush(netOutBuffer);
 
@@ -586,7 +587,7 @@ public class SecureNioChannel extends Ni
         SSLEngineResult unwrap;
         do {
             //prepare the buffer
-            netInBuffer.flip();
+            ((Buffer) netInBuffer).flip();
             //unwrap the data
             unwrap = sslEngine.unwrap(netInBuffer, dst);
             //compact the buffer
@@ -631,7 +632,7 @@ public class SecureNioChannel extends Ni
                 // Something else went wrong
                 throw new IOException(sm.getString("channel.nio.ssl.unwrapFail", unwrap.getStatus()));
             }
-        } while (netInBuffer.position() != 0); //continue to unwrapping as long as the input buffer has stuff
+        } while (((Buffer) netInBuffer).position() != 0); //continue to unwrapping as long as the input buffer has stuff
         return read;
     }
 
@@ -662,12 +663,12 @@ public class SecureNioChannel extends Ni
             }
 
             // The data buffer is empty, we can reuse the entire buffer.
-            netOutBuffer.clear();
+            ((Buffer) netOutBuffer).clear();
 
             SSLEngineResult result = sslEngine.wrap(src, netOutBuffer);
             // The number of bytes written
             int written = result.bytesConsumed();
-            netOutBuffer.flip();
+            ((Buffer) netOutBuffer).flip();
 
             if (result.getStatus() == Status.OK) {
                 if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) tasks();
@@ -712,4 +713,4 @@ public class SecureNioChannel extends Ni
     public ByteBuffer getEmptyBuf() {
         return emptyBuf;
     }
-}
\ No newline at end of file
+}
--- a/java/org/apache/tomcat/util/net/SocketBufferHandler.java
+++ b/java/org/apache/tomcat/util/net/SocketBufferHandler.java
@@ -16,6 +16,7 @@
  */
 package org.apache.tomcat.util.net;
 
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 
 import org.apache.tomcat.util.buf.ByteBufferUtils;
@@ -60,13 +61,13 @@ public class SocketBufferHandler {
                 // Switching to write
                 int remaining = readBuffer.remaining();
                 if (remaining == 0) {
-                    readBuffer.clear();
+                    ((Buffer) readBuffer).clear();
                 } else {
                     readBuffer.compact();
                 }
             } else {
                 // Switching to read
-                readBuffer.flip();
+                ((Buffer) readBuffer).flip();
             }
             this.readBufferConfiguredForWrite = readBufferConFiguredForWrite;
         }
@@ -80,7 +81,7 @@ public class SocketBufferHandler {
 
     public boolean isReadBufferEmpty() {
         if (readBufferConfiguredForWrite) {
-            return readBuffer.position() == 0;
+            return ((Buffer) readBuffer).position() == 0;
         } else {
             return readBuffer.remaining() == 0;
         }
@@ -104,15 +105,15 @@ public class SocketBufferHandler {
                 // Switching to write
                 int remaining = writeBuffer.remaining();
                 if (remaining == 0) {
-                    writeBuffer.clear();
+                    ((Buffer) writeBuffer).clear();
                 } else {
                     writeBuffer.compact();
-                    writeBuffer.position(remaining);
-                    writeBuffer.limit(writeBuffer.capacity());
+                    ((Buffer) writeBuffer).position(remaining);
+                    ((Buffer) writeBuffer).limit(writeBuffer.capacity());
                 }
             } else {
                 // Switching to read
-                writeBuffer.flip();
+                ((Buffer) writeBuffer).flip();
             }
             this.writeBufferConfiguredForWrite = writeBufferConfiguredForWrite;
         }
@@ -135,7 +136,7 @@ public class SocketBufferHandler {
 
     public boolean isWriteBufferEmpty() {
         if (writeBufferConfiguredForWrite) {
-            return writeBuffer.position() == 0;
+            return ((Buffer) writeBuffer).position() == 0;
         } else {
             return writeBuffer.remaining() == 0;
         }
@@ -143,9 +144,9 @@ public class SocketBufferHandler {
 
 
     public void reset() {
-        readBuffer.clear();
+        ((Buffer) readBuffer).clear();
         readBufferConfiguredForWrite = true;
-        writeBuffer.clear();
+        ((Buffer) writeBuffer).clear();
         writeBufferConfiguredForWrite = true;
     }
 
--- a/java/org/apache/tomcat/util/net/SocketWrapperBase.java
+++ b/java/org/apache/tomcat/util/net/SocketWrapperBase.java
@@ -17,6 +17,7 @@
 package org.apache.tomcat.util.net;
 
 import java.io.IOException;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.channels.CompletionHandler;
 import java.util.Iterator;
@@ -457,11 +458,11 @@ public abstract class SocketWrapperBase<
     protected void writeByteBufferBlocking(ByteBuffer from) throws IOException {
         // The socket write buffer capacity is socket.appWriteBufSize
         int limit = socketBufferHandler.getWriteBuffer().capacity();
-        int fromLimit = from.limit();
+        int fromLimit = ((Buffer) from).limit();
         while (from.remaining() >= limit) {
-            from.limit(from.position() + limit);
+            ((Buffer) from).limit(((Buffer) from).position() + limit);
             doWrite(true, from);
-            from.limit(fromLimit);
+            ((Buffer) from).limit(fromLimit);
         }
 
         if (from.remaining() > 0) {
@@ -555,13 +556,13 @@ public abstract class SocketWrapperBase<
     protected boolean writeByteBufferNonBlocking(ByteBuffer from) throws IOException {
         // The socket write buffer capacity is socket.appWriteBufSize
         int limit = socketBufferHandler.getWriteBuffer().capacity();
-        int fromLimit = from.limit();
+        int fromLimit = ((Buffer) from).limit();
         while (from.remaining() >= limit) {
-            int newLimit = from.position() + limit;
-            from.limit(newLimit);
+            int newLimit = ((Buffer) from).position() + limit;
+            ((Buffer) from).limit(newLimit);
             doWrite(false, from);
-            from.limit(fromLimit);
-            if (from.position() != newLimit) {
+            ((Buffer) from).limit(fromLimit);
+            if (((Buffer) from).position() != newLimit) {
                 // Didn't write the whole amount of data in the last
                 // non-blocking write.
                 // Exit the loop.
@@ -1039,10 +1040,10 @@ public abstract class SocketWrapperBase<
     protected static int transfer(ByteBuffer from, ByteBuffer to) {
         int max = Math.min(from.remaining(), to.remaining());
         if (max > 0) {
-            int fromLimit = from.limit();
-            from.limit(from.position() + max);
+            int fromLimit = ((Buffer) from).limit();
+            ((Buffer) from).limit(((Buffer) from).position() + max);
             to.put(from);
-            from.limit(fromLimit);
+            ((Buffer) from).limit(fromLimit);
         }
         return max;
     }
--- a/java/org/apache/tomcat/util/net/TLSClientHelloExtractor.java
+++ b/java/org/apache/tomcat/util/net/TLSClientHelloExtractor.java
@@ -18,6 +18,7 @@ package org.apache.tomcat.util.net;
 
 import java.io.IOException;
 import java.nio.BufferUnderflowException;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
@@ -68,15 +69,15 @@ public class TLSClientHelloExtractor {
     public TLSClientHelloExtractor(ByteBuffer netInBuffer) throws IOException {
         // Buffer is in write mode at this point. Record the current position so
         // the buffer state can be restored at the end of this method.
-        int pos = netInBuffer.position();
-        int limit = netInBuffer.limit();
+        int pos = ((Buffer) netInBuffer).position();
+        int limit = ((Buffer) netInBuffer).limit();
         ExtractorResult result = ExtractorResult.NOT_PRESENT;
         List<Cipher> clientRequestedCiphers = new ArrayList<>();
         List<String> clientRequestedApplicationProtocols = new ArrayList<>();
         String sniValue = null;
         try {
             // Switch to read mode.
-            netInBuffer.flip();
+            ((Buffer) netInBuffer).flip();
 
             // A complete TLS record header is required before we can figure out
             // how many bytes there are in the record.
@@ -164,8 +165,8 @@ public class TLSClientHelloExtractor {
             this.clientRequestedApplicationProtocols = clientRequestedApplicationProtocols;
             this.sniValue = sniValue;
             // Whatever happens, return the buffer to its original state
-            netInBuffer.limit(limit);
-            netInBuffer.position(pos);
+            ((Buffer) netInBuffer).limit(limit);
+            ((Buffer) netInBuffer).position(pos);
         }
     }
 
@@ -203,7 +204,7 @@ public class TLSClientHelloExtractor {
 
 
     private static ExtractorResult handleIncompleteRead(ByteBuffer bb) {
-        if (bb.limit() == bb.capacity()) {
+        if (((Buffer) bb).limit() == bb.capacity()) {
             // Buffer not big enough
             return ExtractorResult.UNDERFLOW;
         } else {
@@ -215,7 +216,7 @@ public class TLSClientHelloExtractor {
 
     private static boolean isAvailable(ByteBuffer bb, int size) {
         if (bb.remaining() < size) {
-            bb.position(bb.limit());
+            ((Buffer) bb).position(((Buffer) bb).limit());
             return false;
         }
         return true;
@@ -243,7 +244,7 @@ public class TLSClientHelloExtractor {
         //       the buffer contains a correctly formatted HTTP request line.
         //       The method, target and protocol are not validated.
         byte chr = 0;
-        bb.position(0);
+        ((Buffer) bb).position(0);
 
         // Skip blank lines
         do {
@@ -324,7 +325,7 @@ public class TLSClientHelloExtractor {
 
 
     private static void skipBytes(ByteBuffer bb, int size) {
-        bb.position(bb.position() + size);
+        ((Buffer) bb).position(((Buffer) bb).position() + size);
     }
 
 
--- a/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java
+++ b/java/org/apache/tomcat/util/net/openssl/OpenSSLEngine.java
@@ -243,8 +243,8 @@ public final class OpenSSLEngine extends
      * Calling this function with src.remaining == 0 is undefined.
      */
     private static int writePlaintextData(final long ssl, final ByteBuffer src) {
-        final int pos = src.position();
-        final int limit = src.limit();
+        final int pos = ((java.nio.Buffer) src).position();
+        final int limit = ((java.nio.Buffer) src).limit();
         final int len = Math.min(limit - pos, MAX_PLAINTEXT_LENGTH);
         final int sslWrote;
 
@@ -252,7 +252,7 @@ public final class OpenSSLEngine extends
             final long addr = Buffer.address(src) + pos;
             sslWrote = SSL.writeToSSL(ssl, addr, len);
             if (sslWrote >= 0) {
-                src.position(pos + sslWrote);
+                ((java.nio.Buffer) src).position(pos + sslWrote);
                 return sslWrote;
             }
         } else {
@@ -260,20 +260,20 @@ public final class OpenSSLEngine extends
             try {
                 final long addr = memoryAddress(buf);
 
-                src.limit(pos + len);
+                ((java.nio.Buffer) src).limit(pos + len);
 
                 buf.put(src);
-                src.limit(limit);
+                ((java.nio.Buffer) src).limit(limit);
 
                 sslWrote = SSL.writeToSSL(ssl, addr, len);
                 if (sslWrote >= 0) {
-                    src.position(pos + sslWrote);
+                    ((java.nio.Buffer) src).position(pos + sslWrote);
                     return sslWrote;
                 } else {
-                    src.position(pos);
+                    ((java.nio.Buffer) src).position(pos);
                 }
             } finally {
-                buf.clear();
+                ((java.nio.Buffer) buf).clear();
                 ByteBufferUtils.cleanDirectBuffer(buf);
             }
         }
@@ -286,13 +286,13 @@ public final class OpenSSLEngine extends
      * Write encrypted data to the OpenSSL network BIO.
      */
     private static int writeEncryptedData(final long networkBIO, final ByteBuffer src) {
-        final int pos = src.position();
+        final int pos = ((java.nio.Buffer) src).position();
         final int len = src.remaining();
         if (src.isDirect()) {
             final long addr = Buffer.address(src) + pos;
             final int netWrote = SSL.writeToBIO(networkBIO, addr, len);
             if (netWrote >= 0) {
-                src.position(pos + netWrote);
+                ((java.nio.Buffer) src).position(pos + netWrote);
                 return netWrote;
             }
         } else {
@@ -304,13 +304,13 @@ public final class OpenSSLEngine extends
 
                 final int netWrote = SSL.writeToBIO(networkBIO, addr, len);
                 if (netWrote >= 0) {
-                    src.position(pos + netWrote);
+                    ((java.nio.Buffer) src).position(pos + netWrote);
                     return netWrote;
                 } else {
-                    src.position(pos);
+                    ((java.nio.Buffer) src).position(pos);
                 }
             } finally {
-                buf.clear();
+                ((java.nio.Buffer) buf).clear();
                 ByteBufferUtils.cleanDirectBuffer(buf);
             }
         }
@@ -323,17 +323,17 @@ public final class OpenSSLEngine extends
      */
     private static int readPlaintextData(final long ssl, final ByteBuffer dst) {
         if (dst.isDirect()) {
-            final int pos = dst.position();
+            final int pos = ((java.nio.Buffer) dst).position();
             final long addr = Buffer.address(dst) + pos;
-            final int len = dst.limit() - pos;
+            final int len = ((java.nio.Buffer) dst).limit() - pos;
             final int sslRead = SSL.readFromSSL(ssl, addr, len);
             if (sslRead > 0) {
-                dst.position(pos + sslRead);
+                ((java.nio.Buffer) dst).position(pos + sslRead);
                 return sslRead;
             }
         } else {
-            final int pos = dst.position();
-            final int limit = dst.limit();
+            final int pos = ((java.nio.Buffer) dst).position();
+            final int limit = ((java.nio.Buffer) dst).limit();
             final int len = Math.min(MAX_ENCRYPTED_PACKET_LENGTH, limit - pos);
             final ByteBuffer buf = ByteBuffer.allocateDirect(len);
             try {
@@ -341,14 +341,14 @@ public final class OpenSSLEngine extends
 
                 final int sslRead = SSL.readFromSSL(ssl, addr, len);
                 if (sslRead > 0) {
-                    buf.limit(sslRead);
-                    dst.limit(pos + sslRead);
+                    ((java.nio.Buffer) buf).limit(sslRead);
+                    ((java.nio.Buffer) dst).limit(pos + sslRead);
                     dst.put(buf);
-                    dst.limit(limit);
+                    ((java.nio.Buffer) dst).limit(limit);
                     return sslRead;
                 }
             } finally {
-                buf.clear();
+                ((java.nio.Buffer) buf).clear();
                 ByteBufferUtils.cleanDirectBuffer(buf);
             }
         }
@@ -361,11 +361,11 @@ public final class OpenSSLEngine extends
      */
     private static int readEncryptedData(final long networkBIO, final ByteBuffer dst, final int pending) {
         if (dst.isDirect() && dst.remaining() >= pending) {
-            final int pos = dst.position();
+            final int pos = ((java.nio.Buffer) dst).position();
             final long addr = Buffer.address(dst) + pos;
             final int bioRead = SSL.readFromBIO(networkBIO, addr, pending);
             if (bioRead > 0) {
-                dst.position(pos + bioRead);
+                ((java.nio.Buffer) dst).position(pos + bioRead);
                 return bioRead;
             }
         } else {
@@ -375,15 +375,15 @@ public final class OpenSSLEngine extends
 
                 final int bioRead = SSL.readFromBIO(networkBIO, addr, pending);
                 if (bioRead > 0) {
-                    buf.limit(bioRead);
-                    int oldLimit = dst.limit();
-                    dst.limit(dst.position() + bioRead);
+                    ((java.nio.Buffer) buf).limit(bioRead);
+                    int oldLimit = ((java.nio.Buffer) dst).limit();
+                    ((java.nio.Buffer) dst).limit(((java.nio.Buffer) dst).position() + bioRead);
                     dst.put(buf);
-                    dst.limit(oldLimit);
+                    ((java.nio.Buffer) dst).limit(oldLimit);
                     return bioRead;
                 }
             } finally {
-                buf.clear();
+                ((java.nio.Buffer) buf).clear();
                 ByteBufferUtils.cleanDirectBuffer(buf);
             }
         }
--- a/java/org/apache/tomcat/websocket/AsyncChannelWrapperSecure.java
+++ b/java/org/apache/tomcat/websocket/AsyncChannelWrapperSecure.java
@@ -18,6 +18,7 @@ package org.apache.tomcat.websocket;
 
 import java.io.EOFException;
 import java.io.IOException;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.channels.AsynchronousSocketChannel;
 import java.nio.channels.CompletionHandler;
@@ -189,7 +190,7 @@ public class AsyncChannelWrapperSecure i
                 for (int i = offset; i < offset + length; i++) {
                     ByteBuffer src = srcs[i];
                     while (src.hasRemaining()) {
-                        socketWriteBuffer.clear();
+                        ((Buffer) socketWriteBuffer).clear();
 
                         // Encrypt the data
                         SSLEngineResult r = sslEngine.wrap(src, socketWriteBuffer);
@@ -215,7 +216,7 @@ public class AsyncChannelWrapperSecure i
                             }
                         }
 
-                        socketWriteBuffer.flip();
+                        ((Buffer) socketWriteBuffer).flip();
 
                         // Do the write
                         int toWrite = r.bytesProduced();
@@ -273,7 +274,7 @@ public class AsyncChannelWrapperSecure i
                         }
                     }
 
-                    socketReadBuffer.flip();
+                    ((Buffer) socketReadBuffer).flip();
 
                     if (socketReadBuffer.hasRemaining()) {
                         // Decrypt the data in the buffer
@@ -359,7 +360,7 @@ public class AsyncChannelWrapperSecure i
             try {
                 sslEngine.beginHandshake();
                 // So the first compact does the right thing
-                socketReadBuffer.position(socketReadBuffer.limit());
+                ((Buffer) socketReadBuffer).position(((Buffer) socketReadBuffer).limit());
 
                 handshakeStatus = sslEngine.getHandshakeStatus();
                 resultStatus = Status.OK;
@@ -369,11 +370,11 @@ public class AsyncChannelWrapperSecure i
                 while(handshaking) {
                     switch (handshakeStatus) {
                         case NEED_WRAP: {
-                            socketWriteBuffer.clear();
+                            ((Buffer) socketWriteBuffer).clear();
                             SSLEngineResult r =
                                     sslEngine.wrap(DUMMY, socketWriteBuffer);
                             checkResult(r, true);
-                            socketWriteBuffer.flip();
+                            ((Buffer) socketWriteBuffer).flip();
                             Future<Integer> fWrite =
                                     socketChannel.write(socketWriteBuffer);
                             fWrite.get();
@@ -381,13 +382,13 @@ public class AsyncChannelWrapperSecure i
                         }
                         case NEED_UNWRAP: {
                             socketReadBuffer.compact();
-                            if (socketReadBuffer.position() == 0 ||
+                            if (((Buffer) socketReadBuffer).position() == 0 ||
                                     resultStatus == Status.BUFFER_UNDERFLOW) {
                                 Future<Integer> fRead =
                                         socketChannel.read(socketReadBuffer);
                                 fRead.get();
                             }
-                            socketReadBuffer.flip();
+                            ((Buffer) socketReadBuffer).flip();
                             SSLEngineResult r =
                                     sslEngine.unwrap(socketReadBuffer, DUMMY);
                             checkResult(r, false);
--- a/java/org/apache/tomcat/websocket/PerMessageDeflate.java
+++ b/java/org/apache/tomcat/websocket/PerMessageDeflate.java
@@ -17,6 +17,7 @@
 package org.apache.tomcat.websocket;
 
 import java.io.IOException;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.List;
@@ -199,23 +200,23 @@ public class PerMessageDeflate implement
             // Space available in destination. Try and fill it.
             try {
                 written = inflater.inflate(
-                        dest.array(), dest.arrayOffset() + dest.position(), dest.remaining());
+                        dest.array(), dest.arrayOffset() + ((Buffer) dest).position(), dest.remaining());
             } catch (DataFormatException e) {
                 throw new IOException(sm.getString("perMessageDeflate.deflateFailed"), e);
             }
-            dest.position(dest.position() + written);
+            ((Buffer) dest).position(((Buffer) dest).position() + written);
 
             if (inflater.needsInput() && !usedEomBytes ) {
                 if (dest.hasRemaining()) {
-                    readBuffer.clear();
+                    ((Buffer) readBuffer).clear();
                     TransformationResult nextResult =
                             next.getMoreData(opCode, fin, (rsv ^ RSV_BITMASK), readBuffer);
                     inflater.setInput(
-                            readBuffer.array(), readBuffer.arrayOffset(), readBuffer.position());
+                            readBuffer.array(), readBuffer.arrayOffset(), ((Buffer) readBuffer).position());
                     if (TransformationResult.UNDERFLOW.equals(nextResult)) {
                         return nextResult;
                     } else if (TransformationResult.END_OF_FRAME.equals(nextResult) &&
-                            readBuffer.position() == 0) {
+                            ((Buffer) readBuffer).position() == 0) {
                         if (fin) {
                             inflater.setInput(EOM_BYTES);
                             usedEomBytes = true;
@@ -337,7 +338,7 @@ public class PerMessageDeflate implement
                         uncompressedPart.getIntermediateHandler();
 
                 deflater.setInput(uncompressedPayload.array(),
-                        uncompressedPayload.arrayOffset() + uncompressedPayload.position(),
+                        uncompressedPayload.arrayOffset() + ((Buffer) uncompressedPayload).position(),
                         uncompressedPayload.remaining());
 
                 int flush = (uncompressedPart.isFin() ? Deflater.SYNC_FLUSH : Deflater.NO_FLUSH);
@@ -347,9 +348,9 @@ public class PerMessageDeflate implement
                     ByteBuffer compressedPayload = writeBuffer;
 
                     int written = deflater.deflate(compressedPayload.array(),
-                            compressedPayload.arrayOffset() + compressedPayload.position(),
+                            compressedPayload.arrayOffset() + ((Buffer) compressedPayload).position(),
                             compressedPayload.remaining(), flush);
-                    compressedPayload.position(compressedPayload.position() + written);
+                    ((Buffer) compressedPayload).position(((Buffer) compressedPayload).position() + written);
 
                     if (!uncompressedPart.isFin() && compressedPayload.hasRemaining() && deflater.needsInput()) {
                         // This message part has been fully processed by the
@@ -366,16 +367,16 @@ public class PerMessageDeflate implement
                     writeBuffer = ByteBuffer.allocate(Constants.DEFAULT_BUFFER_SIZE);
 
                     // Flip the compressed payload ready for writing
-                    compressedPayload.flip();
+                    ((Buffer) compressedPayload).flip();
 
                     boolean fin = uncompressedPart.isFin();
-                    boolean full = compressedPayload.limit() == compressedPayload.capacity();
+                    boolean full = ((Buffer) compressedPayload).limit() == compressedPayload.capacity();
                     boolean needsInput = deflater.needsInput();
                     long blockingWriteTimeoutExpiry = uncompressedPart.getBlockingWriteTimeoutExpiry();
 
                     if (fin && !full && needsInput) {
                         // End of compressed message. Drop EOM bytes and output.
-                        compressedPayload.limit(compressedPayload.limit() - EOM_BYTES.length);
+                        ((Buffer) compressedPayload).limit(((Buffer) compressedPayload).limit() - EOM_BYTES.length);
                         compressedPart = new MessagePart(true, getRsv(uncompressedPart),
                                 opCode, compressedPayload, uncompressedIntermediateHandler,
                                 uncompressedIntermediateHandler, blockingWriteTimeoutExpiry);
@@ -405,7 +406,7 @@ public class PerMessageDeflate implement
                         int eomBufferWritten = deflater.deflate(EOM_BUFFER, 0, EOM_BUFFER.length, Deflater.SYNC_FLUSH);
                         if (eomBufferWritten < EOM_BUFFER.length) {
                             // EOM has just been completed
-                            compressedPayload.limit(compressedPayload.limit() - EOM_BYTES.length + eomBufferWritten);
+                            ((Buffer) compressedPayload).limit(((Buffer) compressedPayload).limit() - EOM_BYTES.length + eomBufferWritten);
                             compressedPart = new MessagePart(true,
                                     getRsv(uncompressedPart), opCode, compressedPayload,
                                     uncompressedIntermediateHandler, uncompressedIntermediateHandler,
--- a/java/org/apache/coyote/http11/Http11OutputBuffer.java
+++ b/java/org/apache/coyote/http11/Http11OutputBuffer.java
@@ -17,6 +17,7 @@
 package org.apache.coyote.http11;
 
 import java.io.IOException;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 
 import org.apache.coyote.ActionCode;
@@ -277,7 +278,7 @@ public class Http11OutputBuffer implemen
      * headers so the error response can be written.
      */
     void resetHeaderBuffer() {
-        headerBuffer.position(0).limit(headerBuffer.capacity());
+        ((Buffer) headerBuffer).position(0).limit(headerBuffer.capacity());
     }
 
 
@@ -305,7 +306,7 @@ public class Http11OutputBuffer implemen
         // Recycle response object
         response.recycle();
         // Reset pointers
-        headerBuffer.position(0).limit(headerBuffer.capacity());
+        ((Buffer) headerBuffer).position(0).limit(headerBuffer.capacity());
         lastActiveFilter = -1;
         responseFinished = false;
         byteCount = 0;
@@ -340,13 +341,13 @@ public class Http11OutputBuffer implemen
     protected void commit() throws IOException {
         response.setCommitted(true);
 
-        if (headerBuffer.position() > 0) {
+        if (((Buffer) headerBuffer).position() > 0) {
             // Sending the response header buffer
-            headerBuffer.flip();
+            ((Buffer) headerBuffer).flip();
             try {
                 socketWrapper.write(isBlocking(), headerBuffer);
             } finally {
-                headerBuffer.position(0).limit(headerBuffer.capacity());
+                ((Buffer) headerBuffer).position(0).limit(headerBuffer.capacity());
             }
         }
     }
@@ -539,7 +540,7 @@ public class Http11OutputBuffer implemen
     private void checkLengthBeforeWrite(int length) {
         // "+ 4": BZ 57509. Reserve space for CR/LF/COLON/SP characters that
         // are put directly into the buffer following this write operation.
-        if (headerBuffer.position() + length + 4 > headerBuffer.capacity()) {
+        if (((Buffer) headerBuffer).position() + length + 4 > headerBuffer.capacity()) {
             throw new HeadersTooLargeException(
                     sm.getString("iob.responseheadertoolarge.error"));
         }
--- a/java/org/apache/tomcat/websocket/WsFrameBase.java
+++ b/java/org/apache/tomcat/websocket/WsFrameBase.java
@@ -17,6 +17,7 @@
 package org.apache.tomcat.websocket;
 
 import java.io.IOException;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
 import java.nio.charset.CharsetDecoder;
@@ -91,7 +92,7 @@ public abstract class WsFrameBase {
 
     public WsFrameBase(WsSession wsSession, Transformation transformation) {
         inputBuffer = ByteBuffer.allocate(Constants.DEFAULT_BUFFER_SIZE);
-        inputBuffer.position(0).limit(0);
+        ((Buffer) inputBuffer).position(0).limit(0);
         messageBufferBinary = ByteBuffer.allocate(wsSession.getMaxBinaryMessageBufferSize());
         messageBufferText = CharBuffer.allocate(wsSession.getMaxTextMessageBufferSize());
         wsSession.setWsFrame(this);
@@ -256,12 +257,12 @@ public abstract class WsFrameBase {
         // Calculate new payload length if necessary
         if (payloadLength == 126) {
             payloadLength = byteArrayToLong(inputBuffer.array(),
-                    inputBuffer.arrayOffset() + inputBuffer.position(), 2);
-            inputBuffer.position(inputBuffer.position() + 2);
+                    inputBuffer.arrayOffset() + ((Buffer) inputBuffer).position(), 2);
+            ((Buffer) inputBuffer).position(((Buffer) inputBuffer).position() + 2);
         } else if (payloadLength == 127) {
             payloadLength = byteArrayToLong(inputBuffer.array(),
-                    inputBuffer.arrayOffset() + inputBuffer.position(), 8);
-            inputBuffer.position(inputBuffer.position() + 8);
+                    inputBuffer.arrayOffset() + ((Buffer) inputBuffer).position(), 8);
+            ((Buffer) inputBuffer).position(((Buffer) inputBuffer).position() + 8);
         }
         if (Util.isControl(opCode)) {
             if (payloadLength > 125) {
@@ -313,13 +314,13 @@ public abstract class WsFrameBase {
         // Control messages have fixed message size so
         // TransformationResult.OVERFLOW is not possible here
 
-        controlBufferBinary.flip();
+        ((Buffer) controlBufferBinary).flip();
         if (opCode == Constants.OPCODE_CLOSE) {
             open = false;
             String reason = null;
             int code = CloseCodes.NORMAL_CLOSURE.getCode();
             if (controlBufferBinary.remaining() == 1) {
-                controlBufferBinary.clear();
+                ((Buffer) controlBufferBinary).clear();
                 // Payload must be zero or 2+ bytes long
                 throw new WsIOException(new CloseReason(
                         CloseCodes.PROTOCOL_ERROR,
@@ -331,8 +332,8 @@ public abstract class WsFrameBase {
                     CoderResult cr = utf8DecoderControl.decode(controlBufferBinary,
                             controlBufferText, true);
                     if (cr.isError()) {
-                        controlBufferBinary.clear();
-                        controlBufferText.clear();
+                        ((Buffer) controlBufferBinary).clear();
+                        ((Buffer) controlBufferText).clear();
                         throw new WsIOException(new CloseReason(
                                 CloseCodes.PROTOCOL_ERROR,
                                 sm.getString("wsFrame.invalidUtf8Close")));
@@ -340,7 +341,7 @@ public abstract class WsFrameBase {
                     // There will be no overflow as the output buffer is big
                     // enough. There will be no underflow as all the data is
                     // passed to the decoder in a single call.
-                    controlBufferText.flip();
+                    ((Buffer) controlBufferText).flip();
                     reason = controlBufferText.toString();
                 }
             }
@@ -357,17 +358,17 @@ public abstract class WsFrameBase {
                 } catch (Throwable t) {
                     handleThrowableOnSend(t);
                 } finally {
-                    controlBufferBinary.clear();
+                    ((Buffer) controlBufferBinary).clear();
                 }
             }
         } else {
             // Should have caught this earlier but just in case...
-            controlBufferBinary.clear();
+            ((Buffer) controlBufferBinary).clear();
             throw new WsIOException(new CloseReason(
                     CloseCodes.PROTOCOL_ERROR,
                     sm.getString("wsFrame.invalidOpCode", Integer.valueOf(opCode))));
         }
-        controlBufferBinary.clear();
+        ((Buffer) controlBufferBinary).clear();
         newFrame();
         return true;
     }
@@ -397,7 +398,7 @@ public abstract class WsFrameBase {
         } catch (Throwable t) {
             handleThrowableOnSend(t);
         } finally {
-            messageBufferText.clear();
+            ((Buffer) messageBufferText).clear();
         }
     }
 
@@ -408,7 +409,7 @@ public abstract class WsFrameBase {
         while (!TransformationResult.END_OF_FRAME.equals(tr)) {
             // Frame not complete - we ran out of something
             // Convert bytes to UTF-8
-            messageBufferBinary.flip();
+            ((Buffer) messageBufferBinary).flip();
             while (true) {
                 CoderResult cr = utf8DecoderMessage.decode(messageBufferBinary, messageBufferText,
                         false);
@@ -419,9 +420,9 @@ public abstract class WsFrameBase {
                 } else if (cr.isOverflow()) {
                     // Ran out of space in text buffer - flush it
                     if (usePartial()) {
-                        messageBufferText.flip();
+                        ((Buffer) messageBufferText).flip();
                         sendMessageText(false);
-                        messageBufferText.clear();
+                        ((Buffer) messageBufferText).clear();
                     } else {
                         throw new WsIOException(new CloseReason(
                                 CloseCodes.TOO_BIG,
@@ -448,7 +449,7 @@ public abstract class WsFrameBase {
             tr = transformation.getMoreData(opCode, fin, rsv, messageBufferBinary);
         }
 
-        messageBufferBinary.flip();
+        ((Buffer) messageBufferBinary).flip();
         boolean last = false;
         // Frame is fully received
         // Convert bytes to UTF-8
@@ -462,9 +463,9 @@ public abstract class WsFrameBase {
             } else if (cr.isOverflow()) {
                 // Ran out of space in text buffer - flush it
                 if (usePartial()) {
-                    messageBufferText.flip();
+                    ((Buffer) messageBufferText).flip();
                     sendMessageText(false);
-                    messageBufferText.clear();
+                    ((Buffer) messageBufferText).clear();
                 } else {
                     throw new WsIOException(new CloseReason(
                             CloseCodes.TOO_BIG,
@@ -477,9 +478,9 @@ public abstract class WsFrameBase {
                     // If partial messages are supported, send what we have
                     // managed to decode
                     if (usePartial()) {
-                        messageBufferText.flip();
+                        ((Buffer) messageBufferText).flip();
                         sendMessageText(false);
-                        messageBufferText.clear();
+                        ((Buffer) messageBufferText).clear();
                     }
                     messageBufferBinary.compact();
                     newFrame();
@@ -491,7 +492,7 @@ public abstract class WsFrameBase {
                 }
             } else {
                 // End of message
-                messageBufferText.flip();
+                ((Buffer) messageBufferText).flip();
                 sendMessageText(true);
 
                 newMessage();
@@ -519,12 +520,12 @@ public abstract class WsFrameBase {
                                 Long.valueOf(payloadLength)));
                 throw new WsIOException(cr);
             }
-            messageBufferBinary.flip();
-            ByteBuffer copy = ByteBuffer.allocate(messageBufferBinary.limit());
+            ((Buffer) messageBufferBinary).flip();
+            ByteBuffer copy = ByteBuffer.allocate(((Buffer) messageBufferBinary).limit());
             copy.put(messageBufferBinary);
-            copy.flip();
+            ((Buffer) copy).flip();
             sendMessageBinary(copy, false);
-            messageBufferBinary.clear();
+            ((Buffer) messageBufferBinary).clear();
             // Read more data
             tr = transformation.getMoreData(opCode, fin, rsv, messageBufferBinary);
         }
@@ -534,12 +535,12 @@ public abstract class WsFrameBase {
         // - partial messages are supported
         // - the message is complete
         if (usePartial() || !continuationExpected) {
-            messageBufferBinary.flip();
-            ByteBuffer copy = ByteBuffer.allocate(messageBufferBinary.limit());
+            ((Buffer) messageBufferBinary).flip();
+            ByteBuffer copy = ByteBuffer.allocate(((Buffer) messageBufferBinary).limit());
             copy.put(messageBufferBinary);
-            copy.flip();
+            ((Buffer) copy).flip();
             sendMessageBinary(copy, !continuationExpected);
-            messageBufferBinary.clear();
+            ((Buffer) messageBufferBinary).clear();
         }
 
         if (continuationExpected) {
@@ -588,8 +589,8 @@ public abstract class WsFrameBase {
 
 
     private void newMessage() {
-        messageBufferBinary.clear();
-        messageBufferText.clear();
+        ((Buffer) messageBufferBinary).clear();
+        ((Buffer) messageBufferText).clear();
         utf8DecoderMessage.reset();
         continuationExpected = false;
         newFrame();
@@ -598,7 +599,7 @@ public abstract class WsFrameBase {
 
     private void newFrame() {
         if (inputBuffer.remaining() == 0) {
-            inputBuffer.position(0).limit(0);
+            ((Buffer) inputBuffer).position(0).limit(0);
         }
 
         maskIndex = 0;
@@ -615,7 +616,7 @@ public abstract class WsFrameBase {
     private void checkRoomHeaders() {
         // Is the start of the current frame too near the end of the input
         // buffer?
-        if (inputBuffer.capacity() - inputBuffer.position() < 131) {
+        if (inputBuffer.capacity() - ((Buffer) inputBuffer).position() < 131) {
             // Limit based on a control frame with a full payload
             makeRoom();
         }
@@ -623,7 +624,7 @@ public abstract class WsFrameBase {
 
 
     private void checkRoomPayload() {
-        if (inputBuffer.capacity() - inputBuffer.position() - payloadLength + payloadWritten < 0) {
+        if (inputBuffer.capacity() - ((Buffer) inputBuffer).position() - payloadLength + payloadWritten < 0) {
             makeRoom();
         }
     }
@@ -631,7 +632,7 @@ public abstract class WsFrameBase {
 
     private void makeRoom() {
         inputBuffer.compact();
-        inputBuffer.flip();
+        ((Buffer) inputBuffer).flip();
     }
 
 
@@ -649,7 +650,7 @@ public abstract class WsFrameBase {
 
     private boolean swallowInput() {
         long toSkip = Math.min(payloadLength - payloadWritten, inputBuffer.remaining());
-        inputBuffer.position(inputBuffer.position() + (int) toSkip);
+        ((Buffer) inputBuffer).position(((Buffer) inputBuffer).position() + (int) toSkip);
         payloadWritten += toSkip;
         if (payloadWritten == payloadLength) {
             if (continuationExpected) {
@@ -944,10 +945,10 @@ public abstract class WsFrameBase {
             long toWrite = Math.min(payloadLength - payloadWritten, inputBuffer.remaining());
             toWrite = Math.min(toWrite, dest.remaining());
 
-            int orgLimit = inputBuffer.limit();
-            inputBuffer.limit(inputBuffer.position() + (int) toWrite);
+            int orgLimit = ((Buffer) inputBuffer).limit();
+            ((Buffer) inputBuffer).limit(((Buffer) inputBuffer).position() + (int) toWrite);
             dest.put(inputBuffer);
-            inputBuffer.limit(orgLimit);
+            ((Buffer) inputBuffer).limit(orgLimit);
             payloadWritten += toWrite;
 
             if (payloadWritten == payloadLength) {
--- a/java/org/apache/tomcat/websocket/WsRemoteEndpointImplBase.java
+++ b/java/org/apache/tomcat/websocket/WsRemoteEndpointImplBase.java
@@ -20,6 +20,7 @@ import java.io.IOException;
 import java.io.OutputStream;
 import java.io.Writer;
 import java.net.SocketTimeoutException;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
 import java.nio.charset.CharsetEncoder;
@@ -240,13 +241,13 @@ public abstract class WsRemoteEndpointIm
         long timeoutExpiry = getTimeoutExpiry();
         boolean isDone = false;
         while (!isDone) {
-            encoderBuffer.clear();
+            ((Buffer) encoderBuffer).clear();
             CoderResult cr = encoder.encode(part, encoderBuffer, true);
             if (cr.isError()) {
                 throw new IllegalArgumentException(cr.toString());
             }
             isDone = !cr.isOverflow();
-            encoderBuffer.flip();
+            ((Buffer) encoderBuffer).flip();
             sendMessageBlock(Constants.OPCODE_TEXT, encoderBuffer, last && isDone, timeoutExpiry);
         }
         stateMachine.complete(last);
@@ -321,7 +322,7 @@ public abstract class WsRemoteEndpointIm
         }
 
         if (payload != null) {
-            payload.clear();
+            ((Buffer) payload).clear();
         }
 
         endMessage(null, null);
@@ -428,7 +429,7 @@ public abstract class WsRemoteEndpointIm
         if (Constants.INTERNAL_OPCODE_FLUSH == mp.getOpCode()) {
             nextFragmented = fragmented;
             nextText = text;
-            outputBuffer.flip();
+            ((Buffer) outputBuffer).flip();
             SendHandler flushHandler = new OutputBufferFlushSendHandler(
                     outputBuffer, mp.getEndHandler());
             doWrite(flushHandler, mp.getBlockingWriteTimeoutExpiry(), outputBuffer);
@@ -477,10 +478,10 @@ public abstract class WsRemoteEndpointIm
             mask = null;
         }
 
-        headerBuffer.clear();
+        ((Buffer) headerBuffer).clear();
         writeHeader(headerBuffer, mp.isFin(), mp.getRsv(), mp.getOpCode(),
                 isMasked(), mp.getPayload(), mask, first);
-        headerBuffer.flip();
+        ((Buffer) headerBuffer).flip();
 
         if (getBatchingAllowed() || isMasked()) {
             // Need to write via output buffer
@@ -744,12 +745,12 @@ public abstract class WsRemoteEndpointIm
         }
 
         // Next write the mask && length length
-        if (payload.limit() < 126) {
-            headerBuffer.put((byte) (payload.limit() | b));
-        } else if (payload.limit() < 65536) {
+        if (((Buffer) payload).limit() < 126) {
+            headerBuffer.put((byte) (((Buffer) payload).limit() | b));
+        } else if (((Buffer) payload).limit() < 65536) {
             headerBuffer.put((byte) (126 | b));
-            headerBuffer.put((byte) (payload.limit() >>> 8));
-            headerBuffer.put((byte) (payload.limit() & 0xFF));
+            headerBuffer.put((byte) (((Buffer) payload).limit() >>> 8));
+            headerBuffer.put((byte) (((Buffer) payload).limit() & 0xFF));
         } else {
             // Will never be more than 2^31-1
             headerBuffer.put((byte) (127 | b));
@@ -757,10 +758,10 @@ public abstract class WsRemoteEndpointIm
             headerBuffer.put((byte) 0);
             headerBuffer.put((byte) 0);
             headerBuffer.put((byte) 0);
-            headerBuffer.put((byte) (payload.limit() >>> 24));
-            headerBuffer.put((byte) (payload.limit() >>> 16));
-            headerBuffer.put((byte) (payload.limit() >>> 8));
-            headerBuffer.put((byte) (payload.limit() & 0xFF));
+            headerBuffer.put((byte) (((Buffer) payload).limit() >>> 24));
+            headerBuffer.put((byte) (((Buffer) payload).limit() >>> 16));
+            headerBuffer.put((byte) (((Buffer) payload).limit() >>> 8));
+            headerBuffer.put((byte) (((Buffer) payload).limit() & 0xFF));
         }
         if (masked) {
             headerBuffer.put(mask[0]);
@@ -793,13 +794,13 @@ public abstract class WsRemoteEndpointIm
         }
 
         public void write() {
-            buffer.clear();
+            ((Buffer) buffer).clear();
             CoderResult cr = encoder.encode(message, buffer, true);
             if (cr.isError()) {
                 throw new IllegalArgumentException(cr.toString());
             }
             isDone = !cr.isOverflow();
-            buffer.flip();
+            ((Buffer) buffer).flip();
             endpoint.startMessage(Constants.OPCODE_TEXT, buffer,
                     isDone && isLast, this);
         }
@@ -860,21 +861,21 @@ public abstract class WsRemoteEndpointIm
             }
             if (headerBuffer.hasRemaining()) {
                 // Still more headers to write, need to flush
-                outputBuffer.flip();
+                ((Buffer) outputBuffer).flip();
                 endpoint.doWrite(this, blockingWriteTimeoutExpiry, outputBuffer);
                 return;
             }
 
             // Write the payload
             int payloadLeft = payload.remaining();
-            int payloadLimit = payload.limit();
+            int payloadLimit = ((Buffer) payload).limit();
             int outputSpace = outputBuffer.remaining();
             int toWrite = payloadLeft;
 
             if (payloadLeft > outputSpace) {
                 toWrite = outputSpace;
                 // Temporarily reduce the limit
-                payload.limit(payload.position() + toWrite);
+                ((Buffer) payload).limit(((Buffer) payload).position() + toWrite);
             }
 
             if (mask == null) {
@@ -892,15 +893,15 @@ public abstract class WsRemoteEndpointIm
 
             if (payloadLeft > outputSpace) {
                 // Restore the original limit
-                payload.limit(payloadLimit);
+                ((Buffer) payload).limit(payloadLimit);
                 // Still more data to write, need to flush
-                outputBuffer.flip();
+                ((Buffer) outputBuffer).flip();
                 endpoint.doWrite(this, blockingWriteTimeoutExpiry, outputBuffer);
                 return;
             }
 
             if (flushRequired) {
-                outputBuffer.flip();
+                ((Buffer) outputBuffer).flip();
                 if (outputBuffer.remaining() == 0) {
                     handler.onResult(SENDRESULT_OK);
                 } else {
@@ -918,7 +919,7 @@ public abstract class WsRemoteEndpointIm
                 if (outputBuffer.hasRemaining()) {
                     endpoint.doWrite(this, blockingWriteTimeoutExpiry, outputBuffer);
                 } else {
-                    outputBuffer.clear();
+                    ((Buffer) outputBuffer).clear();
                     write();
                 }
             } else {
@@ -944,7 +945,7 @@ public abstract class WsRemoteEndpointIm
         @Override
         public void onResult(SendResult result) {
             if (result.isOK()) {
-                outputBuffer.clear();
+                ((Buffer) outputBuffer).clear();
             }
             handler.onResult(result);
         }
@@ -1016,7 +1017,7 @@ public abstract class WsRemoteEndpointIm
 
             // Optimisation. If there is no data to flush then do not send an
             // empty message.
-            if (!Constants.STREAMS_DROP_EMPTY_MESSAGES || buffer.position() > 0) {
+            if (!Constants.STREAMS_DROP_EMPTY_MESSAGES || ((Buffer) buffer).position() > 0) {
                 doWrite(false);
             }
         }
@@ -1035,11 +1036,11 @@ public abstract class WsRemoteEndpointIm
 
         private void doWrite(boolean last) throws IOException {
             if (!Constants.STREAMS_DROP_EMPTY_MESSAGES || used) {
-                buffer.flip();
+                ((Buffer) buffer).flip();
                 endpoint.sendMessageBlock(Constants.OPCODE_BINARY, buffer, last);
             }
             endpoint.stateMachine.complete(last);
-            buffer.clear();
+            ((Buffer) buffer).clear();
         }
     }
 
@@ -1093,7 +1094,7 @@ public abstract class WsRemoteEndpointIm
                         sm.getString("wsRemoteEndpoint.closedWriter"));
             }
 
-            if (!Constants.STREAMS_DROP_EMPTY_MESSAGES || buffer.position() > 0) {
+            if (!Constants.STREAMS_DROP_EMPTY_MESSAGES || ((Buffer) buffer).position() > 0) {
                 doWrite(false);
             }
         }
@@ -1112,9 +1113,9 @@ public abstract class WsRemoteEndpointIm
 
         private void doWrite(boolean last) throws IOException {
             if (!Constants.STREAMS_DROP_EMPTY_MESSAGES || used) {
-                buffer.flip();
+                ((Buffer) buffer).flip();
                 endpoint.sendMessageBlock(buffer, last);
-                buffer.clear();
+                ((Buffer) buffer).clear();
             } else {
                 endpoint.stateMachine.complete(last);
             }
--- a/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerWholeBinary.java
+++ b/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerWholeBinary.java
@@ -19,6 +19,7 @@ package org.apache.tomcat.websocket.pojo
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.lang.reflect.Method;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.List;
@@ -95,7 +96,7 @@ public class PojoMessageHandlerWholeBina
                     return ((Binary<?>) decoder).decode(message);
                 }
             } else {
-                byte[] array = new byte[message.limit() - message.position()];
+                byte[] array = new byte[((Buffer) message).limit() - ((Buffer) message).position()];
                 message.get(array);
                 ByteArrayInputStream bais = new ByteArrayInputStream(array);
                 try {
--- a/java/org/apache/tomcat/util/http/parser/Cookie.java
+++ b/java/org/apache/tomcat/util/http/parser/Cookie.java
@@ -16,6 +16,7 @@
  */
 package org.apache.tomcat.util.http.parser;
 
+import java.nio.Buffer;
 import java.nio.charset.StandardCharsets;
 
 import org.apache.juli.logging.Log;
--- a/test/org/apache/tomcat/websocket/TestWsSession.java
+++ b/test/org/apache/tomcat/websocket/TestWsSession.java
@@ -16,6 +16,7 @@
  */
 package org.apache.tomcat.websocket;
 
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 
 import org.junit.Assert;
@@ -89,13 +90,13 @@ public class TestWsSession {
 
         // Check the position and contents
         if (reasonLength <= 123) {
-            Assert.assertEquals(reasonLength, buf.position());
+            Assert.assertEquals(reasonLength, ((Buffer) buf).position());
             for (int i = 0; i < reasonLength; i++) {
                 Assert.assertEquals('a', buf.get(i));
             }
         } else {
             // Must have been truncated
-            Assert.assertEquals(123, buf.position());
+            Assert.assertEquals(123, ((Buffer) buf).position());
             for (int i = 0; i < 120; i++) {
                 Assert.assertEquals('a', buf.get(i));
             }
--- a/test/org/apache/tomcat/websocket/pojo/TestEncodingDecoding.java
+++ b/test/org/apache/tomcat/websocket/pojo/TestEncodingDecoding.java
@@ -18,6 +18,7 @@ package org.apache.tomcat.websocket.pojo
 
 import java.io.IOException;
 import java.net.URI;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -605,7 +606,7 @@ public class TestEncodingDecoding extend
             reply.put((byte) 0x12);
             reply.put((byte) 0x34);
             reply.put(data);
-            reply.flip();
+            ((Buffer) reply).flip();
             return reply;
         }
     }
@@ -626,7 +627,7 @@ public class TestEncodingDecoding extend
         @Override
         public MsgByte decode(ByteBuffer bb) throws DecodeException {
             MsgByte result = new MsgByte();
-            byte[] data = new byte[bb.limit() - bb.position()];
+            byte[] data = new byte[((Buffer) bb).limit() - ((Buffer) bb).position()];
             bb.get(data);
             result.setData(data);
             return result;
--- a/test/org/apache/coyote/http2/Http2TestBase.java
+++ b/test/org/apache/coyote/http2/Http2TestBase.java
@@ -23,6 +23,7 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.Socket;
 import java.net.SocketException;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
@@ -203,9 +204,9 @@ public abstract class Http2TestBase exte
         if (padding != null) {
             headersPayload.put(padding);
         }
-        headersPayload.flip();
+        ((Buffer) headersPayload).flip();
 
-        ByteUtil.setThreeBytes(frameHeader, 0, headersPayload.limit());
+        ByteUtil.setThreeBytes(frameHeader, 0, ((Buffer) headersPayload).limit());
         frameHeader[3] = FrameType.HEADERS.getIdByte();
         // Flags. end of headers (0x04). end of stream (0x01)
         frameHeader[4] = 0x05;
@@ -236,9 +237,9 @@ public abstract class Http2TestBase exte
         }
         hpackEncoder.encode(mimeHeaders, headersPayload);
 
-        headersPayload.flip();
+        ((Buffer) headersPayload).flip();
 
-        ByteUtil.setThreeBytes(frameHeader, 0, headersPayload.limit());
+        ByteUtil.setThreeBytes(frameHeader, 0, ((Buffer) headersPayload).limit());
         frameHeader[3] = FrameType.HEADERS.getIdByte();
         // Flags. end of stream (0x01)
         frameHeader[4] = 0x01;
@@ -264,9 +265,9 @@ public abstract class Http2TestBase exte
         }
         hpackEncoder.encode(mimeHeaders, headersPayload);
 
-        headersPayload.flip();
+        ((Buffer) headersPayload).flip();
 
-        ByteUtil.setThreeBytes(frameHeader, 0, headersPayload.limit());
+        ByteUtil.setThreeBytes(frameHeader, 0, ((Buffer) headersPayload).limit());
         frameHeader[3] = FrameType.CONTINUATION.getIdByte();
         // Flags. end of headers (0x04)
         frameHeader[4] = 0x04;
@@ -321,9 +322,9 @@ public abstract class Http2TestBase exte
         }
         hpackEncoder.encode(headers, headersPayload);
 
-        headersPayload.flip();
+        ((Buffer) headersPayload).flip();
 
-        ByteUtil.setThreeBytes(headersFrameHeader, 0, headersPayload.limit());
+        ByteUtil.setThreeBytes(headersFrameHeader, 0, ((Buffer) headersPayload).limit());
         headersFrameHeader[3] = FrameType.HEADERS.getIdByte();
         // Flags. end of headers (0x04)
         headersFrameHeader[4] = 0x04;
@@ -333,21 +334,21 @@ public abstract class Http2TestBase exte
         // Data
         if (padding != null) {
             dataPayload.put((byte) (padding.length & 0xFF));
-            dataPayload.limit(dataPayload.capacity() - padding.length);
+            ((Buffer) dataPayload).limit(dataPayload.capacity() - padding.length);
         }
 
         while (dataPayload.hasRemaining()) {
             dataPayload.put((byte) 'x');
         }
         if (padding != null && padding.length > 0) {
-            dataPayload.limit(dataPayload.capacity());
+            ((Buffer) dataPayload).limit(dataPayload.capacity());
             dataPayload.put(padding);
         }
 
-        dataPayload.flip();
+        ((Buffer) dataPayload).flip();
 
         // Size
-        ByteUtil.setThreeBytes(dataFrameHeader, 0, dataPayload.limit());
+        ByteUtil.setThreeBytes(dataFrameHeader, 0, ((Buffer) dataPayload).limit());
         // Data is type 0
         // Flags: End of stream 1, Padding 8
         if (trailersPayload == null) {
@@ -366,9 +367,9 @@ public abstract class Http2TestBase exte
             trailerHeaders.addValue(TRAILER_HEADER_NAME).setString(TRAILER_HEADER_VALUE);
             hpackEncoder.encode(trailerHeaders, trailersPayload);
 
-            trailersPayload.flip();
+            ((Buffer) trailersPayload).flip();
 
-            ByteUtil.setThreeBytes(trailersFrameHeader, 0, trailersPayload.limit());
+            ByteUtil.setThreeBytes(trailersFrameHeader, 0, ((Buffer) trailersPayload).limit());
             trailersFrameHeader[3] = FrameType.HEADERS.getIdByte();
             // Flags. end of headers (0x04) and end of stream (0x01)
             trailersFrameHeader[4] = 0x05;
@@ -617,7 +618,7 @@ public abstract class Http2TestBase exte
         }
 
         String response = new String(data.array(), data.arrayOffset(),
-                data.arrayOffset() + data.position(), StandardCharsets.ISO_8859_1);
+                data.arrayOffset() + ((Buffer) data).position(), StandardCharsets.ISO_8859_1);
 
         return response.split("\r\n");
     }
@@ -860,9 +861,9 @@ public abstract class Http2TestBase exte
 
         @Override
         public boolean fill(boolean block, ByteBuffer data, int len) throws IOException {
-            boolean result = fill(block, data.array(), data.arrayOffset() + data.position(), len);
+            boolean result = fill(block, data.array(), data.arrayOffset() + ((Buffer) data).position(), len);
             if (result) {
-                data.position(data.position() + len);
+                ((Buffer) data).position(((Buffer) data).position() + len);
             }
             return result;
         }
@@ -928,9 +929,9 @@ public abstract class Http2TestBase exte
         @Override
         public void endRequestBodyFrame(int streamId) throws Http2Exception {
             if (bodyBuffer != null) {
-                if (bodyBuffer.limit() > 0) {
+                if (((Buffer) bodyBuffer).limit() > 0) {
                     trace.append(lastStreamId + "-Body-");
-                    bodyBuffer.flip();
+                    ((Buffer) bodyBuffer).flip();
                     while (bodyBuffer.hasRemaining()) {
                         trace.append((char) bodyBuffer.get());
                     }
--- a/java/org/apache/tomcat/websocket/WsPongMessage.java
+++ b/java/org/apache/tomcat/websocket/WsPongMessage.java
@@ -16,6 +16,7 @@
  */
 package org.apache.tomcat.websocket;
 
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 
 import javax.websocket.PongMessage;
@@ -26,7 +27,7 @@ public class WsPongMessage implements Po
 
 
     public WsPongMessage(ByteBuffer applicationData) {
-        byte[] dst = new byte[applicationData.limit()];
+        byte[] dst = new byte[((Buffer) applicationData).limit()];
         applicationData.get(dst);
         this.applicationData = ByteBuffer.wrap(dst);
     }
--- a/java/org/apache/tomcat/websocket/WsWebSocketContainer.java
+++ b/java/org/apache/tomcat/websocket/WsWebSocketContainer.java
@@ -27,6 +27,7 @@ import java.net.ProxySelector;
 import java.net.SocketAddress;
 import java.net.URI;
 import java.net.URISyntaxException;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.channels.AsynchronousChannelGroup;
 import java.nio.channels.AsynchronousSocketChannel;
@@ -524,7 +525,7 @@ public class WsWebSocketContainer implem
 
     private static void writeRequest(AsyncChannelWrapper channel, ByteBuffer request,
             long timeout) throws TimeoutException, InterruptedException, ExecutionException {
-        int toWrite = request.limit();
+        int toWrite = ((Buffer) request).limit();
 
         Future<Integer> fWrite = channel.write(request);
         Integer thisWrite = fWrite.get(timeout, TimeUnit.MILLISECONDS);
@@ -738,7 +739,7 @@ public class WsWebSocketContainer implem
         // Terminating CRLF
         result.put(CRLF);
 
-        result.flip();
+        ((Buffer) result).flip();
 
         return result;
     }
@@ -777,14 +778,14 @@ public class WsWebSocketContainer implem
         while (!readHeaders) {
             // On entering loop buffer will be empty and at the start of a new
             // loop the buffer will have been fully read.
-            response.clear();
+            ((Buffer) response).clear();
             // Blocking read
             Future<Integer> read = channel.read(response);
             Integer bytesRead = read.get(timeout, TimeUnit.MILLISECONDS);
             if (bytesRead.intValue() == -1) {
                 throw new EOFException();
             }
-            response.flip();
+            ((Buffer) response).flip();
             while (response.hasRemaining() && !readHeaders) {
                 if (line == null) {
                     line = readLine(response);
--- a/java/org/apache/coyote/http11/filters/IdentityInputFilter.java
+++ b/java/org/apache/coyote/http11/filters/IdentityInputFilter.java
@@ -18,6 +18,7 @@
 package org.apache.coyote.http11.filters;
 
 import java.io.IOException;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 
@@ -142,7 +143,7 @@ public class IdentityInputFilter impleme
                     // The chunk is longer than the number of bytes remaining
                     // in the body; changing the chunk length to the number
                     // of bytes remaining
-                    handler.getByteBuffer().limit(handler.getByteBuffer().position() + (int) remaining);
+                    ((Buffer) handler.getByteBuffer()).limit(((Buffer) handler.getByteBuffer()).position() + (int) remaining);
                     result = (int) remaining;
                 } else {
                     result = nRead;
@@ -154,7 +155,7 @@ public class IdentityInputFilter impleme
                 // No more bytes left to be read : return -1 and clear the
                 // buffer
                 if (handler.getByteBuffer() != null) {
-                    handler.getByteBuffer().position(0).limit(0);
+                    ((Buffer) handler.getByteBuffer()).position(0).limit(0);
                 }
                 result = -1;
             }
--- a/test/org/apache/tomcat/websocket/TestWsRemoteEndpoint.java
+++ b/test/org/apache/tomcat/websocket/TestWsRemoteEndpoint.java
@@ -19,6 +19,7 @@ package org.apache.tomcat.websocket;
 import java.io.OutputStream;
 import java.io.Writer;
 import java.net.URI;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
@@ -162,7 +163,7 @@ public class TestWsRemoteEndpoint extend
             @SuppressWarnings("unchecked")
             List<ByteBuffer> messages = (List<ByteBuffer>) handler.getMessages();
             for (ByteBuffer message : messages) {
-                byte[] bytes = new byte[message.limit()];
+                byte[] bytes = new byte[((Buffer) message).limit()];
                 message.get(bytes);
                 results.add(new String(bytes, StandardCharsets.UTF_8));
             }
--- a/test/org/apache/coyote/http2/TestHttp2Limits.java
+++ b/test/org/apache/coyote/http2/TestHttp2Limits.java
@@ -17,6 +17,7 @@
 package org.apache.coyote.http2;
 
 import java.io.IOException;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.util.ArrayList;
 import java.util.List;
@@ -220,11 +221,11 @@ public class TestHttp2Limits extends Htt
         Exception e = null;
         try {
             int written = 0;
-            int left = headersPayload.limit() - written;
+            int left = ((Buffer) headersPayload).limit() - written;
             while (left > 0) {
                 int thisTime = Math.min(left, maxHeaderPayloadSize);
                 populateFrameHeader(frameHeader, written, left, thisTime, 3);
-                writeFrame(frameHeader, headersPayload, headersPayload.limit() - left,
+                writeFrame(frameHeader, headersPayload, ((Buffer) headersPayload).limit() - left,
                         thisTime, delayms);
                 left -= thisTime;
                 written += thisTime;
@@ -283,9 +284,9 @@ public class TestHttp2Limits extends Htt
         if (state != State.COMPLETE) {
             throw new Exception("Unable to build headers");
         }
-        headersPayload.flip();
+        ((Buffer) headersPayload).flip();
 
-        log.debug("Headers payload generated of size [" + headersPayload.limit() + "]");
+        log.debug("Headers payload generated of size [" + ((Buffer) headersPayload).limit() + "]");
     }
 
 
@@ -375,7 +376,7 @@ public class TestHttp2Limits extends Htt
         }
 
         populateHeadersPayload(headersPayload, customHeaders, "/cookie");
-        populateFrameHeader(frameHeader, 0, headersPayload.limit(), headersPayload.limit(), 3);
+        populateFrameHeader(frameHeader, 0, ((Buffer) headersPayload).limit(), ((Buffer) headersPayload).limit(), 3);
 
         writeFrame(frameHeader, headersPayload);
 
--- a/java/org/apache/coyote/http2/Http2Parser.java
+++ b/java/org/apache/coyote/http2/Http2Parser.java
@@ -17,6 +17,7 @@
 package org.apache.coyote.http2;
 
 import java.io.IOException;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 
@@ -414,7 +415,7 @@ class Http2Parser {
             // headerReadBuffer in write mode
             input.fill(true, headerReadBuffer, toRead);
             // switch to read mode
-            headerReadBuffer.flip();
+            ((Buffer) headerReadBuffer).flip();
             try {
                 hpackDecoder.decode(headerReadBuffer);
             } catch (HpackException hpe) {
@@ -434,14 +435,14 @@ class Http2Parser {
                 hpackDecoder.getHeaderEmitter().setHeaderException(headerException);
             }
 
-            if (hpackDecoder.isHeaderSizeExceeded(headerReadBuffer.position())) {
+            if (hpackDecoder.isHeaderSizeExceeded(((Buffer) headerReadBuffer).position())) {
                 StreamException headerException = new StreamException(sm.getString(
                         "http2Parser.headerLimitSize", connectionId, Integer.valueOf(streamId)),
                         Http2Error.ENHANCE_YOUR_CALM, streamId);
                 hpackDecoder.getHeaderEmitter().setHeaderException(headerException);
             }
 
-            if (hpackDecoder.isHeaderSwallowSizeExceeded(headerReadBuffer.position())) {
+            if (hpackDecoder.isHeaderSwallowSizeExceeded(((Buffer) headerReadBuffer).position())) {
                 throw new ConnectionException(sm.getString("http2Parser.headerLimitSize",
                         connectionId, Integer.valueOf(streamId)), Http2Error.ENHANCE_YOUR_CALM);
             }
@@ -451,7 +452,7 @@ class Http2Parser {
 
     private void onHeadersComplete(int streamId) throws Http2Exception {
         // Any left over data is a compression error
-        if (headerReadBuffer.position() > 0) {
+        if (((Buffer) headerReadBuffer).position() > 0) {
             throw new ConnectionException(
                     sm.getString("http2Parser.processFrameHeaders.decodingDataLeft"),
                     Http2Error.COMPRESSION_ERROR);
--- a/test/org/apache/tomcat/util/buf/TestUtf8.java
+++ b/test/org/apache/tomcat/util/buf/TestUtf8.java
@@ -16,6 +16,7 @@
  */
 package org.apache.tomcat.util.buf;
 
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
 import java.nio.charset.CharsetDecoder;
@@ -579,7 +580,7 @@ public class TestUtf8 {
         // an invalid sequence has been provided
         for (int i = 0; i < len; i++) {
             bb.put((byte) testCase.input[i]);
-            bb.flip();
+            ((Buffer) bb).flip();
             CoderResult cr = decoder.decode(bb, cb, false);
             if (cr.isError()) {
                 int expected =  testCase.invalidIndex;
@@ -604,11 +605,11 @@ public class TestUtf8 {
         decoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
 
         // Add each byte one at a time.
-        bb.clear();
-        cb.clear();
+        ((Buffer) bb).clear();
+        ((Buffer) cb).clear();
         for (int i = 0; i < len; i++) {
             bb.put((byte) testCase.input[i]);
-            bb.flip();
+            ((Buffer) bb).flip();
             CoderResult cr = decoder.decode(bb, cb, false);
             if (cr.isError()) {
                 Assert.fail(testCase.description);
@@ -617,12 +618,12 @@ public class TestUtf8 {
         }
         // For incomplete sequences at the end of the input need to tell
         // the decoder the input has ended
-        bb.flip();
+        ((Buffer) bb).flip();
         CoderResult cr = decoder.decode(bb, cb, true);
         if (cr.isError()) {
             Assert.fail(testCase.description);
         }
-        cb.flip();
+        ((Buffer) cb).flip();
 
         String expected = testCase.outputReplaced;
         if ((flags & REPLACE_SWALLOWS_TRAILER) != 0) {
--- a/test/org/apache/coyote/http2/TestHpack.java
+++ b/test/org/apache/coyote/http2/TestHpack.java
@@ -16,6 +16,7 @@
  */
 package org.apache.coyote.http2;
 
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 
 import org.junit.Assert;
@@ -34,13 +35,13 @@ public class TestHpack {
         ByteBuffer output = ByteBuffer.allocate(512);
         HpackEncoder encoder = new HpackEncoder();
         encoder.encode(headers, output);
-        output.flip();
+        ((Buffer) output).flip();
         // Size is supposed to be 33 without huffman, or 27 with it
         // TODO: use the HpackHeaderFunction to enable huffman predictably
         Assert.assertEquals(27, output.remaining());
-        output.clear();
+        ((Buffer) output).clear();
         encoder.encode(headers, output);
-        output.flip();
+        ((Buffer) output).flip();
         // Size is now 3 after using the table
         Assert.assertEquals(3, output.remaining());
     }
@@ -54,15 +55,15 @@ public class TestHpack {
         ByteBuffer output = ByteBuffer.allocate(512);
         HpackEncoder encoder = new HpackEncoder();
         encoder.encode(headers, output);
-        output.flip();
+        ((Buffer) output).flip();
         MimeHeaders headers2 = new MimeHeaders();
         HpackDecoder decoder = new HpackDecoder();
         decoder.setHeaderEmitter(new HeadersListener(headers2));
         decoder.decode(output);
         // Redo (table is supposed to be updated)
-        output.clear();
+        ((Buffer) output).clear();
         encoder.encode(headers, output);
-        output.flip();
+        ((Buffer) output).flip();
         headers2.recycle();
         Assert.assertEquals(3, output.remaining());
         // Check that the decoder is using the table right
@@ -120,7 +121,7 @@ public class TestHpack {
         // by another byte
         output.array()[7] = (byte) -122;
         output.put((byte) -1);
-        output.flip();
+        ((Buffer) output).flip();
         MimeHeaders headers2 = new MimeHeaders();
         HpackDecoder decoder = new HpackDecoder();
         decoder.setHeaderEmitter(new HeadersListener(headers2));
@@ -136,7 +137,7 @@ public class TestHpack {
         ByteBuffer output = ByteBuffer.allocate(512);
         HpackEncoder encoder = new HpackEncoder();
         encoder.encode(headers, output);
-        output.flip();
+        ((Buffer) output).flip();
         MimeHeaders headers2 = new MimeHeaders();
         HpackDecoder decoder = new HpackDecoder();
         decoder.setHeaderEmitter(new HeadersListener(headers2));
--- a/test/org/apache/coyote/http11/upgrade/TestUpgradeInternalHandler.java
+++ b/test/org/apache/coyote/http11/upgrade/TestUpgradeInternalHandler.java
@@ -25,6 +25,7 @@ import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
 import java.io.Writer;
 import java.net.Socket;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.channels.CompletionHandler;
 import java.util.concurrent.TimeUnit;
@@ -210,7 +211,7 @@ public class TestUpgradeInternalHandler
         }
 
         private void write(ByteBuffer buffer) {
-            buffer.flip();
+            ((Buffer) buffer).flip();
             CompletionState state = wrapper.write(true, 10, TimeUnit.SECONDS, null, SocketWrapperBase.COMPLETE_WRITE, new CompletionHandler<Long, Void>() {
                 @Override
                 public void completed(Long result, Void attachment) {
--- a/java/org/apache/tomcat/websocket/WsSession.java
+++ b/java/org/apache/tomcat/websocket/WsSession.java
@@ -18,6 +18,7 @@ package org.apache.tomcat.websocket;
 
 import java.io.IOException;
 import java.net.URI;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.channels.WritePendingException;
 import java.nio.charset.StandardCharsets;
@@ -587,7 +588,7 @@ public class WsSession implements Sessio
         if (reason != null && reason.length() > 0) {
             appendCloseReasonWithTruncation(msg, reason);
         }
-        msg.flip();
+        ((Buffer) msg).flip();
         try {
             wsRemoteEndpoint.sendMessageBlock(Constants.OPCODE_CLOSE, msg, true);
         } catch (IOException | WritePendingException e) {
--- a/java/org/apache/tomcat/websocket/server/WsFrameServer.java
+++ b/java/org/apache/tomcat/websocket/server/WsFrameServer.java
@@ -18,6 +18,7 @@ package org.apache.tomcat.websocket.serv
 
 import java.io.EOFException;
 import java.io.IOException;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 
 import org.apache.juli.logging.Log;
@@ -67,10 +68,10 @@ public class WsFrameServer extends WsFra
 
         while (isOpen() && !isSuspended()) {
             // Fill up the input buffer with as much data as we can
-            inputBuffer.mark();
-            inputBuffer.position(inputBuffer.limit()).limit(inputBuffer.capacity());
+            ((Buffer) inputBuffer).mark();
+            ((Buffer) inputBuffer).position(((Buffer) inputBuffer).limit()).limit(inputBuffer.capacity());
             int read = socketWrapper.read(false, inputBuffer);
-            inputBuffer.limit(inputBuffer.position()).reset();
+            ((Buffer) inputBuffer).limit(((Buffer) inputBuffer).position()).reset();
             if (read < 0) {
                 throw new EOFException();
             } else if (read == 0) {
--- a/java/org/apache/tomcat/websocket/WsFrameClient.java
+++ b/java/org/apache/tomcat/websocket/WsFrameClient.java
@@ -18,6 +18,7 @@ package org.apache.tomcat.websocket;
 
 import java.io.EOFException;
 import java.io.IOException;
+import java.nio.Buffer;
 import java.nio.ByteBuffer;
 import java.nio.channels.CompletionHandler;
 
@@ -76,25 +77,25 @@ public class WsFrameClient extends WsFra
                         // and then a new socket read will be performed
                         return;
                     }
-                    inputBuffer.mark();
-                    inputBuffer.position(inputBuffer.limit()).limit(inputBuffer.capacity());
+                    ((Buffer) inputBuffer).mark();
+                    ((Buffer) inputBuffer).position(((Buffer) inputBuffer).limit()).limit(inputBuffer.capacity());
 
                     int toCopy = Math.min(response.remaining(), inputBuffer.remaining());
 
                     // Copy remaining bytes read in HTTP phase to input buffer used by
                     // frame processing
 
-                    int orgLimit = response.limit();
-                    response.limit(response.position() + toCopy);
+                    int orgLimit = ((Buffer) response).limit();
+                    ((Buffer) response).limit(((Buffer) response).position() + toCopy);
                     inputBuffer.put(response);
-                    response.limit(orgLimit);
+                    ((Buffer) response).limit(orgLimit);
 
-                    inputBuffer.limit(inputBuffer.position()).reset();
+                    ((Buffer) inputBuffer).limit(((Buffer) inputBuffer).position()).reset();
 
                     // Process the data we have
                     processInputBuffer();
                 }
-                response.clear();
+                ((Buffer) response).clear();
 
                 // Get some more data
                 if (isOpen()) {
@@ -159,7 +160,7 @@ public class WsFrameClient extends WsFra
                 // No data to process
                 return;
             }
-            response.flip();
+            ((Buffer) response).flip();
             doResumeProcessing(true);
         }
 
@@ -169,7 +170,7 @@ public class WsFrameClient extends WsFra
                 // response will be empty if this exception is thrown
                 response = ByteBuffer
                         .allocate(((ReadBufferOverflowException) exc).getMinBufferSize());
-                response.flip();
+                ((Buffer) response).flip();
                 doResumeProcessing(false);
             } else {
                 close(exc);
