core, alts, cronet: fix ByteBuffer covariant method usages (#7349)

Java 9 introduces overridden methods with covariant return types for the following methods in java.nio.ByteBuffer:

- position​(int newPosition)
- limit​(int newLimit)
- flip​()
- clear​()
- mark​()
- reset​()
- rewind​()

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 issue appears even with source and target 8 or lower in compilation parameters).
The solution is to cast ByteBuffer instances to Buffer before calling the method.
This commit is contained in:
Chengyuan Zhang 2020-08-25 17:21:34 -07:00 committed by GitHub
parent 720df64fd2
commit c30505df04
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 84 additions and 74 deletions

View File

@ -17,6 +17,7 @@
package io.grpc.alts.internal; package io.grpc.alts.internal;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import java.nio.Buffer;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
@ -63,10 +64,10 @@ public final class AltsFraming {
} }
Producer producer = new Producer(); Producer producer = new Producer();
ByteBuffer inputAlias = input.duplicate(); ByteBuffer inputAlias = input.duplicate();
inputAlias.limit(input.position() + dataSize); ((Buffer) inputAlias).limit(input.position() + dataSize);
producer.readBytes(inputAlias); producer.readBytes(inputAlias);
producer.flush(); producer.flush();
input.position(inputAlias.position()); ((Buffer) input).position(inputAlias.position());
ByteBuffer output = producer.getRawFrame(); ByteBuffer output = producer.getRawFrame();
return output; return output;
} }
@ -166,10 +167,10 @@ public final class AltsFraming {
int frameLength = buffer.position() + getFrameSuffixLength(); int frameLength = buffer.position() + getFrameSuffixLength();
// Set the limit and move to the start. // Set the limit and move to the start.
buffer.flip(); ((Buffer) buffer).flip();
// Advance the limit to allow a crypto suffix. // Advance the limit to allow a crypto suffix.
buffer.limit(buffer.limit() + getFrameSuffixLength()); ((Buffer) buffer).limit(buffer.limit() + getFrameSuffixLength());
// Write the data length and the message type. // Write the data length and the message type.
int dataLength = frameLength - FRAME_LENGTH_HEADER_SIZE; int dataLength = frameLength - FRAME_LENGTH_HEADER_SIZE;
@ -178,17 +179,17 @@ public final class AltsFraming {
buffer.putInt(MESSAGE_TYPE); buffer.putInt(MESSAGE_TYPE);
// Move the position back to 0, the frame is ready. // Move the position back to 0, the frame is ready.
buffer.position(0); ((Buffer) buffer).position(0);
isComplete = true; isComplete = true;
} }
/** Resets the state, preparing to construct a new frame. Must be called between frames. */ /** Resets the state, preparing to construct a new frame. Must be called between frames. */
private void reset() { private void reset() {
buffer.clear(); ((Buffer) buffer).clear();
// Save some space for framing, we'll fill that in later. // Save some space for framing, we'll fill that in later.
buffer.position(getFramePrefixLength()); ((Buffer) buffer).position(getFramePrefixLength());
buffer.limit(buffer.limit() - getFrameSuffixLength()); ((Buffer) buffer).limit(buffer.limit() - getFrameSuffixLength());
isComplete = false; isComplete = false;
} }
@ -279,7 +280,7 @@ public final class AltsFraming {
// internal buffer is large enough. // internal buffer is large enough.
if (buffer.position() == FRAME_LENGTH_HEADER_SIZE && input.hasRemaining()) { if (buffer.position() == FRAME_LENGTH_HEADER_SIZE && input.hasRemaining()) {
ByteBuffer bufferAlias = buffer.duplicate(); ByteBuffer bufferAlias = buffer.duplicate();
bufferAlias.flip(); ((Buffer) bufferAlias).flip();
bufferAlias.order(ByteOrder.LITTLE_ENDIAN); bufferAlias.order(ByteOrder.LITTLE_ENDIAN);
int dataLength = bufferAlias.getInt(); int dataLength = bufferAlias.getInt();
if (dataLength < FRAME_MESSAGE_TYPE_HEADER_SIZE || dataLength > MAX_DATA_LENGTH) { if (dataLength < FRAME_MESSAGE_TYPE_HEADER_SIZE || dataLength > MAX_DATA_LENGTH) {
@ -292,7 +293,7 @@ public final class AltsFraming {
buffer.order(ByteOrder.LITTLE_ENDIAN); buffer.order(ByteOrder.LITTLE_ENDIAN);
buffer.putInt(dataLength); buffer.putInt(dataLength);
} }
buffer.limit(frameLength); ((Buffer) buffer).limit(frameLength);
} }
// TODO: Similarly extract and check message type. // TODO: Similarly extract and check message type.
@ -300,7 +301,7 @@ public final class AltsFraming {
// Read the remaining data into the internal buffer. // Read the remaining data into the internal buffer.
copy(buffer, input); copy(buffer, input);
if (!buffer.hasRemaining()) { if (!buffer.hasRemaining()) {
buffer.flip(); ((Buffer) buffer).flip();
isComplete = true; isComplete = true;
} }
return isComplete; return isComplete;
@ -323,7 +324,7 @@ public final class AltsFraming {
/** Resets the state, preparing to parse a new frame. Must be called between frames. */ /** Resets the state, preparing to parse a new frame. Must be called between frames. */
private void reset() { private void reset() {
buffer.clear(); ((Buffer) buffer).clear();
isComplete = false; isComplete = false;
} }
@ -356,9 +357,9 @@ public final class AltsFraming {
} else { } else {
int count = Math.min(dst.remaining(), src.remaining()); int count = Math.min(dst.remaining(), src.remaining());
ByteBuffer slice = src.slice(); ByteBuffer slice = src.slice();
slice.limit(count); ((Buffer) slice).limit(count);
dst.put(slice); dst.put(slice);
src.position(src.position() + count); ((Buffer) src).position(src.position() + count);
} }
} }
} }

View File

@ -23,6 +23,7 @@ import com.google.protobuf.ByteString;
import io.grpc.Status; import io.grpc.Status;
import io.grpc.alts.internal.HandshakerServiceGrpc.HandshakerServiceStub; import io.grpc.alts.internal.HandshakerServiceGrpc.HandshakerServiceStub;
import java.io.IOException; import java.io.IOException;
import java.nio.Buffer;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.util.logging.Level; import java.util.logging.Level;
@ -199,7 +200,7 @@ class AltsHandshakerClient {
throw new GeneralSecurityException(e); throw new GeneralSecurityException(e);
} }
handleResponse(resp); handleResponse(resp);
inBytes.position(inBytes.position() + resp.getBytesConsumed()); ((Buffer) inBytes).position(inBytes.position() + resp.getBytesConsumed());
return resp.getOutFrames().asReadOnlyByteBuffer(); return resp.getOutFrames().asReadOnlyByteBuffer();
} }
@ -227,7 +228,7 @@ class AltsHandshakerClient {
throw new GeneralSecurityException(e); throw new GeneralSecurityException(e);
} }
handleResponse(resp); handleResponse(resp);
inBytes.position(inBytes.position() + resp.getBytesConsumed()); ((Buffer) inBytes).position(inBytes.position() + resp.getBytesConsumed());
return resp.getOutFrames().asReadOnlyByteBuffer(); return resp.getOutFrames().asReadOnlyByteBuffer();
} }

View File

@ -22,6 +22,7 @@ import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Preconditions; import com.google.common.base.Preconditions;
import io.grpc.alts.internal.HandshakerServiceGrpc.HandshakerServiceStub; import io.grpc.alts.internal.HandshakerServiceGrpc.HandshakerServiceStub;
import io.netty.buffer.ByteBufAllocator; import io.netty.buffer.ByteBufAllocator;
import java.nio.Buffer;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.util.ArrayList; import java.util.ArrayList;
@ -151,10 +152,10 @@ public final class AltsTsiHandshaker implements TsiHandshaker {
ByteBuffer outputFrameAlias = outputFrame; ByteBuffer outputFrameAlias = outputFrame;
if (outputFrame.remaining() > bytes.remaining()) { if (outputFrame.remaining() > bytes.remaining()) {
outputFrameAlias = outputFrame.duplicate(); outputFrameAlias = outputFrame.duplicate();
outputFrameAlias.limit(outputFrameAlias.position() + bytes.remaining()); ((Buffer) outputFrameAlias).limit(outputFrameAlias.position() + bytes.remaining());
} }
bytes.put(outputFrameAlias); bytes.put(outputFrameAlias);
outputFrame.position(outputFrameAlias.position()); ((Buffer) outputFrame).position(outputFrameAlias.position());
} }
/** /**

View File

@ -19,6 +19,7 @@ package io.grpc.alts.internal;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import java.nio.Buffer;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
@ -38,7 +39,7 @@ public class AltsFramingTest {
buffer.order(ByteOrder.LITTLE_ENDIAN); buffer.order(ByteOrder.LITTLE_ENDIAN);
buffer.putInt(-1); // write invalid length buffer.putInt(-1); // write invalid length
buffer.put((byte) 0); // write some byte buffer.put((byte) 0); // write some byte
buffer.flip(); ((Buffer) buffer).flip();
try { try {
parser.readBytes(buffer); parser.readBytes(buffer);
@ -56,7 +57,7 @@ public class AltsFramingTest {
buffer.order(ByteOrder.LITTLE_ENDIAN); buffer.order(ByteOrder.LITTLE_ENDIAN);
buffer.putInt(AltsFraming.getFrameMessageTypeHeaderSize() - 1); // write invalid length buffer.putInt(AltsFraming.getFrameMessageTypeHeaderSize() - 1); // write invalid length
buffer.put((byte) 0); // write some byte buffer.put((byte) 0); // write some byte
buffer.flip(); ((Buffer) buffer).flip();
try { try {
parser.readBytes(buffer); parser.readBytes(buffer);
@ -74,7 +75,7 @@ public class AltsFramingTest {
buffer.order(ByteOrder.LITTLE_ENDIAN); buffer.order(ByteOrder.LITTLE_ENDIAN);
buffer.putInt(AltsFraming.getMaxDataLength() + 1); // write invalid length buffer.putInt(AltsFraming.getMaxDataLength() + 1); // write invalid length
buffer.put((byte) 0); // write some byte buffer.put((byte) 0); // write some byte
buffer.flip(); ((Buffer) buffer).flip();
try { try {
parser.readBytes(buffer); parser.readBytes(buffer);
@ -97,7 +98,7 @@ public class AltsFramingTest {
buffer.putInt(6); // default message type buffer.putInt(6); // default message type
buffer.put(new byte[dataLength - AltsFraming.getFrameMessageTypeHeaderSize()]); // write data buffer.put(new byte[dataLength - AltsFraming.getFrameMessageTypeHeaderSize()]); // write data
buffer.put((byte) 0); buffer.put((byte) 0);
buffer.flip(); ((Buffer) buffer).flip();
parser.readBytes(buffer); parser.readBytes(buffer);
@ -116,7 +117,7 @@ public class AltsFramingTest {
buffer.putInt(dataLength); // write invalid length buffer.putInt(dataLength); // write invalid length
buffer.putInt(6); // default message type buffer.putInt(6); // default message type
buffer.put((byte) 0); buffer.put((byte) 0);
buffer.flip(); ((Buffer) buffer).flip();
parser.readBytes(buffer); parser.readBytes(buffer);

View File

@ -29,6 +29,7 @@ import static org.mockito.Mockito.when;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.protobuf.ByteString; import com.google.protobuf.ByteString;
import java.nio.Buffer;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import org.junit.Before; import org.junit.Before;
@ -178,7 +179,7 @@ public class AltsHandshakerClientTest {
.thenReturn(MockAltsHandshakerResp.getOkResponse(BYTES_CONSUMED)); .thenReturn(MockAltsHandshakerResp.getOkResponse(BYTES_CONSUMED));
ByteBuffer inBytes = ByteBuffer.allocate(IN_BYTES_SIZE); ByteBuffer inBytes = ByteBuffer.allocate(IN_BYTES_SIZE);
inBytes.position(PREFIX_POSITION); ((Buffer) inBytes).position(PREFIX_POSITION);
ByteBuffer outFrame = handshaker.startServerHandshake(inBytes); ByteBuffer outFrame = handshaker.startServerHandshake(inBytes);
assertEquals(ByteString.copyFrom(outFrame), MockAltsHandshakerResp.getOutFrame()); assertEquals(ByteString.copyFrom(outFrame), MockAltsHandshakerResp.getOutFrame());

View File

@ -26,6 +26,7 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import com.google.protobuf.ByteString; import com.google.protobuf.ByteString;
import java.nio.Buffer;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@ -112,7 +113,7 @@ public class AltsTsiHandshakerTest {
verify(mockServer, never()).startClientHandshake(); verify(mockServer, never()).startClientHandshake();
verify(mockServer, never()).next(ArgumentMatchers.<ByteBuffer>any()); verify(mockServer, never()).next(ArgumentMatchers.<ByteBuffer>any());
// Mock transport buffer all consumed by processBytesFromPeer and there is an output frame. // Mock transport buffer all consumed by processBytesFromPeer and there is an output frame.
transportBuffer.position(transportBuffer.limit()); ((Buffer) transportBuffer).position(transportBuffer.limit());
when(mockServer.startServerHandshake(transportBuffer)).thenReturn(outputFrame); when(mockServer.startServerHandshake(transportBuffer)).thenReturn(outputFrame);
when(mockServer.isFinished()).thenReturn(false); when(mockServer.isFinished()).thenReturn(false);
@ -127,7 +128,7 @@ public class AltsTsiHandshakerTest {
verify(mockServer, never()).next(ArgumentMatchers.<ByteBuffer>any()); verify(mockServer, never()).next(ArgumentMatchers.<ByteBuffer>any());
// Mock transport buffer all consumed by processBytesFromPeer and output frame is empty. // Mock transport buffer all consumed by processBytesFromPeer and output frame is empty.
// Expect processBytesFromPeer return False, because more data are needed from the peer. // Expect processBytesFromPeer return False, because more data are needed from the peer.
transportBuffer.position(transportBuffer.limit()); ((Buffer) transportBuffer).position(transportBuffer.limit());
when(mockServer.startServerHandshake(transportBuffer)).thenReturn(emptyOutputFrame); when(mockServer.startServerHandshake(transportBuffer)).thenReturn(emptyOutputFrame);
when(mockServer.isFinished()).thenReturn(false); when(mockServer.isFinished()).thenReturn(false);
@ -174,7 +175,7 @@ public class AltsTsiHandshakerTest {
when(mockClient.isFinished()).thenReturn(false); when(mockClient.isFinished()).thenReturn(false);
handshakerClient.getBytesToSendToPeer(transportBuffer); handshakerClient.getBytesToSendToPeer(transportBuffer);
transportBuffer.position(transportBuffer.limit()); ((Buffer) transportBuffer).position(transportBuffer.limit());
assertFalse(handshakerClient.processBytesFromPeer(transportBuffer)); assertFalse(handshakerClient.processBytesFromPeer(transportBuffer));
} }

View File

@ -27,6 +27,7 @@ import io.netty.buffer.ByteBuf;
import io.netty.util.ReferenceCounted; import io.netty.util.ReferenceCounted;
import io.netty.util.ResourceLeakDetector; import io.netty.util.ResourceLeakDetector;
import io.netty.util.ResourceLeakDetector.Level; import io.netty.util.ResourceLeakDetector.Level;
import java.nio.Buffer;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.util.ArrayList; import java.util.ArrayList;
@ -86,11 +87,11 @@ public class FakeTsiTest {
byte[] transportBufferBytes = new byte[TsiTest.getDefaultTransportBufferSize()]; byte[] transportBufferBytes = new byte[TsiTest.getDefaultTransportBufferSize()];
ByteBuffer transportBuffer = ByteBuffer.wrap(transportBufferBytes); ByteBuffer transportBuffer = ByteBuffer.wrap(transportBufferBytes);
transportBuffer.limit(0); // Start off with an empty buffer ((Buffer) transportBuffer).limit(0); // Start off with an empty buffer
transportBuffer.clear(); ((Buffer) transportBuffer).clear();
clientHandshaker.getBytesToSendToPeer(transportBuffer); clientHandshaker.getBytesToSendToPeer(transportBuffer);
transportBuffer.flip(); ((Buffer) transportBuffer).flip();
assertEquals( assertEquals(
FakeTsiHandshaker.State.CLIENT_INIT.toString().trim(), FakeTsiHandshaker.State.CLIENT_INIT.toString().trim(),
new String(transportBufferBytes, 4, transportBuffer.remaining(), UTF_8).trim()); new String(transportBufferBytes, 4, transportBuffer.remaining(), UTF_8).trim());
@ -99,14 +100,14 @@ public class FakeTsiTest {
assertFalse(transportBuffer.hasRemaining()); assertFalse(transportBuffer.hasRemaining());
// client shouldn't offer any more bytes // client shouldn't offer any more bytes
transportBuffer.clear(); ((Buffer) transportBuffer).clear();
clientHandshaker.getBytesToSendToPeer(transportBuffer); clientHandshaker.getBytesToSendToPeer(transportBuffer);
transportBuffer.flip(); ((Buffer) transportBuffer).flip();
assertFalse(transportBuffer.hasRemaining()); assertFalse(transportBuffer.hasRemaining());
transportBuffer.clear(); ((Buffer) transportBuffer).clear();
serverHandshaker.getBytesToSendToPeer(transportBuffer); serverHandshaker.getBytesToSendToPeer(transportBuffer);
transportBuffer.flip(); ((Buffer) transportBuffer).flip();
assertEquals( assertEquals(
FakeTsiHandshaker.State.SERVER_INIT.toString().trim(), FakeTsiHandshaker.State.SERVER_INIT.toString().trim(),
new String(transportBufferBytes, 4, transportBuffer.remaining(), UTF_8).trim()); new String(transportBufferBytes, 4, transportBuffer.remaining(), UTF_8).trim());
@ -115,14 +116,14 @@ public class FakeTsiTest {
assertFalse(transportBuffer.hasRemaining()); assertFalse(transportBuffer.hasRemaining());
// server shouldn't offer any more bytes // server shouldn't offer any more bytes
transportBuffer.clear(); ((Buffer) transportBuffer).clear();
serverHandshaker.getBytesToSendToPeer(transportBuffer); serverHandshaker.getBytesToSendToPeer(transportBuffer);
transportBuffer.flip(); ((Buffer) transportBuffer).flip();
assertFalse(transportBuffer.hasRemaining()); assertFalse(transportBuffer.hasRemaining());
transportBuffer.clear(); ((Buffer) transportBuffer).clear();
clientHandshaker.getBytesToSendToPeer(transportBuffer); clientHandshaker.getBytesToSendToPeer(transportBuffer);
transportBuffer.flip(); ((Buffer) transportBuffer).flip();
assertEquals( assertEquals(
FakeTsiHandshaker.State.CLIENT_FINISHED.toString().trim(), FakeTsiHandshaker.State.CLIENT_FINISHED.toString().trim(),
new String(transportBufferBytes, 4, transportBuffer.remaining(), UTF_8).trim()); new String(transportBufferBytes, 4, transportBuffer.remaining(), UTF_8).trim());
@ -131,14 +132,14 @@ public class FakeTsiTest {
assertFalse(transportBuffer.hasRemaining()); assertFalse(transportBuffer.hasRemaining());
// client shouldn't offer any more bytes // client shouldn't offer any more bytes
transportBuffer.clear(); ((Buffer) transportBuffer).clear();
clientHandshaker.getBytesToSendToPeer(transportBuffer); clientHandshaker.getBytesToSendToPeer(transportBuffer);
transportBuffer.flip(); ((Buffer) transportBuffer).flip();
assertFalse(transportBuffer.hasRemaining()); assertFalse(transportBuffer.hasRemaining());
transportBuffer.clear(); ((Buffer) transportBuffer).clear();
serverHandshaker.getBytesToSendToPeer(transportBuffer); serverHandshaker.getBytesToSendToPeer(transportBuffer);
transportBuffer.flip(); ((Buffer) transportBuffer).flip();
assertEquals( assertEquals(
FakeTsiHandshaker.State.SERVER_FINISHED.toString().trim(), FakeTsiHandshaker.State.SERVER_FINISHED.toString().trim(),
new String(transportBufferBytes, 4, transportBuffer.remaining(), UTF_8).trim()); new String(transportBufferBytes, 4, transportBuffer.remaining(), UTF_8).trim());
@ -147,9 +148,9 @@ public class FakeTsiTest {
assertFalse(transportBuffer.hasRemaining()); assertFalse(transportBuffer.hasRemaining());
// server shouldn't offer any more bytes // server shouldn't offer any more bytes
transportBuffer.clear(); ((Buffer) transportBuffer).clear();
serverHandshaker.getBytesToSendToPeer(transportBuffer); serverHandshaker.getBytesToSendToPeer(transportBuffer);
transportBuffer.flip(); ((Buffer) transportBuffer).flip();
assertFalse(transportBuffer.hasRemaining()); assertFalse(transportBuffer.hasRemaining());
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException e) {
throw new AssertionError(e); throw new AssertionError(e);

View File

@ -20,6 +20,7 @@ import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.protobuf.ByteString; import com.google.protobuf.ByteString;
import io.grpc.Status; import io.grpc.Status;
import java.nio.Buffer;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
import java.security.SecureRandom; import java.security.SecureRandom;
@ -62,7 +63,7 @@ class MockAltsHandshakerResp {
buffer.order(ByteOrder.LITTLE_ENDIAN); buffer.order(ByteOrder.LITTLE_ENDIAN);
buffer.putInt(frameSize); buffer.putInt(frameSize);
buffer.put(TEST_OUT_FRAME.getBytes(UTF_8)); buffer.put(TEST_OUT_FRAME.getBytes(UTF_8));
buffer.flip(); ((Buffer) buffer).flip();
return ByteString.copyFrom(buffer); return ByteString.copyFrom(buffer);
} }

View File

@ -26,6 +26,7 @@ import io.grpc.alts.internal.TsiFrameProtector.Consumer;
import io.netty.buffer.ByteBuf; import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import io.netty.buffer.UnpooledByteBufAllocator; import io.netty.buffer.UnpooledByteBufAllocator;
import java.nio.Buffer;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.util.ArrayList; import java.util.ArrayList;
@ -83,7 +84,7 @@ public final class TsiTest {
byte[] transportBufferBytes = new byte[transportBufferSize]; byte[] transportBufferBytes = new byte[transportBufferSize];
ByteBuffer transportBuffer = ByteBuffer.wrap(transportBufferBytes); ByteBuffer transportBuffer = ByteBuffer.wrap(transportBufferBytes);
transportBuffer.limit(0); // Start off with an empty buffer ((Buffer) transportBuffer).limit(0); // Start off with an empty buffer
while (clientHandshaker.isInProgress() || serverHandshaker.isInProgress()) { while (clientHandshaker.isInProgress() || serverHandshaker.isInProgress()) {
for (TsiHandshaker handshaker : new TsiHandshaker[] {clientHandshaker, serverHandshaker}) { for (TsiHandshaker handshaker : new TsiHandshaker[] {clientHandshaker, serverHandshaker}) {
@ -94,9 +95,9 @@ public final class TsiTest {
} }
// Put new bytes on the wire, if needed. // Put new bytes on the wire, if needed.
if (handshaker.isInProgress()) { if (handshaker.isInProgress()) {
transportBuffer.clear(); ((Buffer) transportBuffer).clear();
handshaker.getBytesToSendToPeer(transportBuffer); handshaker.getBytesToSendToPeer(transportBuffer);
transportBuffer.flip(); ((Buffer) transportBuffer).flip();
} }
} }
} }

View File

@ -102,18 +102,16 @@ public class CompositeReadableBuffer extends AbstractReadableBuffer {
@Override @Override
public void readBytes(final ByteBuffer dest) { public void readBytes(final ByteBuffer dest) {
// Use Buffer instead of ByteBuffer for JDK 9+ compatibility.
final Buffer destAsBuffer = dest;
execute(new ReadOperation() { execute(new ReadOperation() {
@Override @Override
public int readInternal(ReadableBuffer buffer, int length) { public int readInternal(ReadableBuffer buffer, int length) {
// Change the limit so that only lengthToCopy bytes are available. // Change the limit so that only lengthToCopy bytes are available.
int prevLimit = destAsBuffer.limit(); int prevLimit = dest.limit();
destAsBuffer.limit(destAsBuffer.position() + length); ((Buffer) dest).limit(dest.position() + length);
// Write the bytes and restore the original limit. // Write the bytes and restore the original limit.
buffer.readBytes(dest); buffer.readBytes(dest);
destAsBuffer.limit(prevLimit); ((Buffer) dest).limit(prevLimit);
return 0; return 0;
} }
}, dest.remaining()); }, dest.remaining());

View File

@ -210,8 +210,7 @@ public final class ReadableBuffers {
* A {@link ReadableBuffer} that is backed by a {@link ByteBuffer}. * A {@link ReadableBuffer} that is backed by a {@link ByteBuffer}.
*/ */
private static class ByteReadableBufferWrapper extends AbstractReadableBuffer { private static class ByteReadableBufferWrapper extends AbstractReadableBuffer {
// Use Buffer instead of ByteBuffer for JDK 9+ compatibility. final ByteBuffer bytes;
final Buffer bytes;
ByteReadableBufferWrapper(ByteBuffer bytes) { ByteReadableBufferWrapper(ByteBuffer bytes) {
this.bytes = Preconditions.checkNotNull(bytes, "bytes"); this.bytes = Preconditions.checkNotNull(bytes, "bytes");
@ -225,19 +224,19 @@ public final class ReadableBuffers {
@Override @Override
public int readUnsignedByte() { public int readUnsignedByte() {
checkReadable(1); checkReadable(1);
return ((ByteBuffer) bytes).get() & 0xFF; return bytes.get() & 0xFF;
} }
@Override @Override
public void skipBytes(int length) { public void skipBytes(int length) {
checkReadable(length); checkReadable(length);
bytes.position(bytes.position() + length); ((Buffer) bytes).position(bytes.position() + length);
} }
@Override @Override
public void readBytes(byte[] dest, int destOffset, int length) { public void readBytes(byte[] dest, int destOffset, int length) {
checkReadable(length); checkReadable(length);
((ByteBuffer) bytes).get(dest, destOffset, length); bytes.get(dest, destOffset, length);
} }
@Override @Override
@ -248,10 +247,10 @@ public final class ReadableBuffers {
// Change the limit so that only length bytes are available. // Change the limit so that only length bytes are available.
int prevLimit = bytes.limit(); int prevLimit = bytes.limit();
bytes.limit(bytes.position() + length); ((Buffer) bytes).limit(bytes.position() + length);
// Write the bytes and restore the original limit. // Write the bytes and restore the original limit.
dest.put((ByteBuffer) bytes); dest.put(bytes);
bytes.limit(prevLimit); bytes.limit(prevLimit);
} }
@ -260,11 +259,11 @@ public final class ReadableBuffers {
checkReadable(length); checkReadable(length);
if (hasArray()) { if (hasArray()) {
dest.write(array(), arrayOffset(), length); dest.write(array(), arrayOffset(), length);
bytes.position(bytes.position() + length); ((Buffer) bytes).position(bytes.position() + length);
} else { } else {
// The buffer doesn't support array(). Copy the data to an intermediate buffer. // The buffer doesn't support array(). Copy the data to an intermediate buffer.
byte[] array = new byte[length]; byte[] array = new byte[length];
((ByteBuffer) bytes).get(array); bytes.get(array);
dest.write(array); dest.write(array);
} }
} }
@ -272,9 +271,9 @@ public final class ReadableBuffers {
@Override @Override
public ByteReadableBufferWrapper readBytes(int length) { public ByteReadableBufferWrapper readBytes(int length) {
checkReadable(length); checkReadable(length);
ByteBuffer buffer = ((ByteBuffer) bytes).duplicate(); ByteBuffer buffer = bytes.duplicate();
((Buffer) buffer).limit(bytes.position() + length); ((Buffer) buffer).limit(bytes.position() + length);
bytes.position(bytes.position() + length); ((Buffer) bytes).position(bytes.position() + length);
return new ByteReadableBufferWrapper(buffer); return new ByteReadableBufferWrapper(buffer);
} }
@ -285,7 +284,7 @@ public final class ReadableBuffers {
@Override @Override
public byte[] array() { public byte[] array() {
return ((ByteBuffer) bytes).array(); return bytes.array();
} }
@Override @Override

View File

@ -23,6 +23,7 @@ import static org.mockito.Mockito.verify;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.nio.Buffer;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
@ -119,17 +120,17 @@ public class CompositeReadableBufferTest {
ByteBuffer byteBuffer = ByteBuffer.allocate(EXPECTED_VALUE.length()); ByteBuffer byteBuffer = ByteBuffer.allocate(EXPECTED_VALUE.length());
int remaining = EXPECTED_VALUE.length(); int remaining = EXPECTED_VALUE.length();
byteBuffer.limit(1); ((Buffer) byteBuffer).limit(1);
composite.readBytes(byteBuffer); composite.readBytes(byteBuffer);
remaining--; remaining--;
assertEquals(remaining, composite.readableBytes()); assertEquals(remaining, composite.readableBytes());
byteBuffer.limit(byteBuffer.limit() + 5); ((Buffer) byteBuffer).limit(byteBuffer.limit() + 5);
composite.readBytes(byteBuffer); composite.readBytes(byteBuffer);
remaining -= 5; remaining -= 5;
assertEquals(remaining, composite.readableBytes()); assertEquals(remaining, composite.readableBytes());
byteBuffer.limit(byteBuffer.limit() + remaining); ((Buffer) byteBuffer).limit(byteBuffer.limit() + remaining);
composite.readBytes(byteBuffer); composite.readBytes(byteBuffer);
assertEquals(0, composite.readableBytes()); assertEquals(0, composite.readableBytes());
assertEquals(EXPECTED_VALUE, new String(byteBuffer.array(), UTF_8)); assertEquals(EXPECTED_VALUE, new String(byteBuffer.array(), UTF_8));

View File

@ -21,6 +21,7 @@ import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.nio.Buffer;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.Arrays; import java.util.Arrays;
import org.junit.Test; import org.junit.Test;
@ -86,7 +87,7 @@ public abstract class ReadableBufferTestBase {
ReadableBuffer buffer = buffer(); ReadableBuffer buffer = buffer();
ByteBuffer byteBuffer = ByteBuffer.allocate(msg.length()); ByteBuffer byteBuffer = ByteBuffer.allocate(msg.length());
buffer.readBytes(byteBuffer); buffer.readBytes(byteBuffer);
byteBuffer.flip(); ((Buffer) byteBuffer).flip();
byte[] array = new byte[msg.length()]; byte[] array = new byte[msg.length()];
byteBuffer.get(array); byteBuffer.get(array);
assertArrayEquals(msg.getBytes(UTF_8), array); assertArrayEquals(msg.getBytes(UTF_8), array);
@ -98,7 +99,7 @@ public abstract class ReadableBufferTestBase {
ReadableBuffer buffer = buffer(); ReadableBuffer buffer = buffer();
ByteBuffer byteBuffer = ByteBuffer.allocate(2); ByteBuffer byteBuffer = ByteBuffer.allocate(2);
buffer.readBytes(byteBuffer); buffer.readBytes(byteBuffer);
byteBuffer.flip(); ((Buffer) byteBuffer).flip();
byte[] array = new byte[2]; byte[] array = new byte[2];
byteBuffer.get(array); byteBuffer.get(array);
assertArrayEquals(new byte[]{'h', 'e'}, array); assertArrayEquals(new byte[]{'h', 'e'}, array);

View File

@ -42,6 +42,7 @@ import io.grpc.internal.TransportTracer;
import io.grpc.internal.WritableBuffer; import io.grpc.internal.WritableBuffer;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.nio.Buffer;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.ArrayList; import java.util.ArrayList;
@ -218,7 +219,7 @@ class CronetClientStream extends AbstractClientStream {
ByteBuffer byteBuffer; ByteBuffer byteBuffer;
if (buffer != null) { if (buffer != null) {
byteBuffer = ((CronetWritableBuffer) buffer).buffer(); byteBuffer = ((CronetWritableBuffer) buffer).buffer();
byteBuffer.flip(); ((Buffer) byteBuffer).flip();
} else { } else {
byteBuffer = EMPTY_BUFFER; byteBuffer = EMPTY_BUFFER;
} }
@ -471,7 +472,7 @@ class CronetClientStream extends AbstractClientStream {
@Override @Override
public void onReadCompleted(BidirectionalStream stream, UrlResponseInfo info, public void onReadCompleted(BidirectionalStream stream, UrlResponseInfo info,
ByteBuffer buffer, boolean endOfStream) { ByteBuffer buffer, boolean endOfStream) {
buffer.flip(); ((Buffer) buffer).flip();
if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) { if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) {
Log.v(LOG_TAG, "onReadCompleted. Size=" + buffer.remaining()); Log.v(LOG_TAG, "onReadCompleted. Size=" + buffer.remaining());
} }

View File

@ -43,6 +43,7 @@ import io.grpc.internal.TransportTracer;
import io.grpc.internal.WritableBuffer; import io.grpc.internal.WritableBuffer;
import io.grpc.testing.TestMethodDescriptors; import io.grpc.testing.TestMethodDescriptors;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.nio.Buffer;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.util.ArrayList; import java.util.ArrayList;
@ -176,7 +177,7 @@ public final class CronetClientStreamTest {
// 5 writes are called. // 5 writes are called.
verify(cronetStream, times(5)).write(isA(ByteBuffer.class), eq(false)); verify(cronetStream, times(5)).write(isA(ByteBuffer.class), eq(false));
ByteBuffer fakeBuffer = ByteBuffer.allocateDirect(8); ByteBuffer fakeBuffer = ByteBuffer.allocateDirect(8);
fakeBuffer.position(8); ((Buffer) fakeBuffer).position(8);
verify(cronetStream, times(2)).flush(); verify(cronetStream, times(2)).flush();
// 5 onWriteCompleted callbacks for previous writes. // 5 onWriteCompleted callbacks for previous writes.
@ -294,7 +295,7 @@ public final class CronetClientStreamTest {
ArgumentCaptor<ByteBuffer> bufferCaptor = ArgumentCaptor.forClass(ByteBuffer.class); ArgumentCaptor<ByteBuffer> bufferCaptor = ArgumentCaptor.forClass(ByteBuffer.class);
verify(cronetStream, times(1)).write(bufferCaptor.capture(), isA(Boolean.class)); verify(cronetStream, times(1)).write(bufferCaptor.capture(), isA(Boolean.class));
ByteBuffer buffer = bufferCaptor.getValue(); ByteBuffer buffer = bufferCaptor.getValue();
buffer.position(request.length()); ((Buffer) buffer).position(request.length());
verify(cronetStream, times(1)).flush(); verify(cronetStream, times(1)).flush();
// Receive response header // Receive response header