Skip to content

Commit

Permalink
Don't directly call ByteBuffer, etc. methods that have covariant retu…
Browse files Browse the repository at this point in the history
…rns in Java 9+.

Doing so produces a jar that doesn't work under Java 8.

This CL addresses the currently existing problematic calls (by calling the methods on the supertype Buffer instead), but we should also add safeguards.

The normal solution to this general problem is to use --release, but doing so here is complicated.

For more information, see #3990

RELNOTES=n/a

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=327654073
  • Loading branch information
cpovirk authored and netdpb committed Aug 21, 2020
1 parent 23be71a commit 406a4ea
Show file tree
Hide file tree
Showing 20 changed files with 220 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ protected void update(byte[] b, int off, int len) {
protected void update(ByteBuffer b) {
if (b.hasArray()) {
update(b.array(), b.arrayOffset() + b.position(), b.remaining());
b.position(b.limit());
Java8Compatibility.position(b, b.limit());
} else {
for (int remaining = b.remaining(); remaining > 0; remaining--) {
update(b.get());
Expand All @@ -67,7 +67,7 @@ private Hasher update(int bytes) {
try {
update(scratch.array(), 0, bytes);
} finally {
scratch.clear();
Java8Compatibility.clear(scratch);
}
return this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public Hasher putBytes(byte[] bytes, int off, int len) {
public Hasher putBytes(ByteBuffer bytes) {
int pos = bytes.position();
for (Hasher hasher : hashers) {
bytes.position(pos);
Java8Compatibility.position(bytes, pos);
hasher.putBytes(bytes);
}
return this;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public Hasher putBytes(byte[] bytes, int off, int len) {
public Hasher putBytes(ByteBuffer b) {
if (b.hasArray()) {
putBytes(b.array(), b.arrayOffset() + b.position(), b.remaining());
b.position(b.limit());
Java8Compatibility.position(b, b.limit());
} else {
for (int remaining = b.remaining(); remaining > 0; remaining--) {
putByte(b.get());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,13 @@ protected AbstractStreamingHasher(int chunkSize, int bufferSize) {
* <p>This implementation simply pads with zeros and delegates to {@link #process(ByteBuffer)}.
*/
protected void processRemaining(ByteBuffer bb) {
bb.position(bb.limit()); // move at the end
bb.limit(chunkSize + 7); // get ready to pad with longs
Java8Compatibility.position(bb, bb.limit()); // move at the end
Java8Compatibility.limit(bb, chunkSize + 7); // get ready to pad with longs
while (bb.position() < chunkSize) {
bb.putLong(0);
}
bb.limit(chunkSize);
bb.flip();
Java8Compatibility.limit(bb, chunkSize);
Java8Compatibility.flip(bb);
process(bb);
}

Expand Down Expand Up @@ -179,10 +179,10 @@ public final Hasher putLong(long l) {
@Override
public final HashCode hash() {
munch();
buffer.flip();
Java8Compatibility.flip(buffer);
if (buffer.remaining() > 0) {
processRemaining(buffer);
buffer.position(buffer.limit());
Java8Compatibility.position(buffer, buffer.limit());
}
return makeHash();
}
Expand All @@ -203,7 +203,7 @@ private void munchIfFull() {
}

private void munch() {
buffer.flip();
Java8Compatibility.flip(buffer);
while (buffer.remaining() >= chunkSize) {
// we could limit the buffer to ensure process() does not read more than
// chunkSize number of bytes, but we trust the implementations
Expand Down
43 changes: 43 additions & 0 deletions android/guava/src/com/google/common/hash/Java8Compatibility.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright (C) 2020 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/

package com.google.common.hash;

import com.google.common.annotations.GwtIncompatible;
import java.nio.Buffer;

/**
* Wrappers around {@link Buffer} methods that are covariantly overridden in Java 9+. See
* https://github.com/google/guava/issues/3990
*/
@GwtIncompatible
final class Java8Compatibility {
static void clear(Buffer b) {
b.clear();
}

static void flip(Buffer b) {
b.flip();
}

static void limit(Buffer b, int limit) {
b.limit(limit);
}

static void position(Buffer b, int position) {
b.position(position);
}

private Java8Compatibility() {}
}
4 changes: 2 additions & 2 deletions android/guava/src/com/google/common/io/ByteStreams.java
Original file line number Diff line number Diff line change
Expand Up @@ -145,11 +145,11 @@ public static long copy(ReadableByteChannel from, WritableByteChannel to) throws
ByteBuffer buf = ByteBuffer.wrap(createBuffer());
long total = 0;
while (from.read(buf) != -1) {
buf.flip();
Java8Compatibility.flip(buf);
while (buf.hasRemaining()) {
total += to.write(buf);
}
buf.clear();
Java8Compatibility.clear(buf);
}
return total;
}
Expand Down
6 changes: 3 additions & 3 deletions android/guava/src/com/google/common/io/CharStreams.java
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,10 @@ public static long copy(Readable from, Appendable to) throws IOException {
long total = 0;
CharBuffer buf = createBuffer();
while (from.read(buf) != -1) {
buf.flip();
Java8Compatibility.flip(buf);
to.append(buf);
total += buf.remaining();
buf.clear();
Java8Compatibility.clear(buf);
}
return total;
}
Expand Down Expand Up @@ -243,7 +243,7 @@ public static long exhaust(Readable readable) throws IOException {
CharBuffer buf = createBuffer();
while ((read = readable.read(buf)) != -1) {
total += read;
buf.clear();
Java8Compatibility.clear(buf);
}
return total;
}
Expand Down
43 changes: 43 additions & 0 deletions android/guava/src/com/google/common/io/Java8Compatibility.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright (C) 2020 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/

package com.google.common.io;

import com.google.common.annotations.GwtIncompatible;
import java.nio.Buffer;

/**
* Wrappers around {@link Buffer} methods that are covariantly overridden in Java 9+. See
* https://github.com/google/guava/issues/3990
*/
@GwtIncompatible
final class Java8Compatibility {
static void clear(Buffer b) {
b.clear();
}

static void flip(Buffer b) {
b.flip();
}

static void limit(Buffer b, int limit) {
b.limit(limit);
}

static void position(Buffer b, int position) {
b.position(position);
}

private Java8Compatibility() {}
}
2 changes: 1 addition & 1 deletion android/guava/src/com/google/common/io/LineReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public LineReader(Readable readable) {
@CanIgnoreReturnValue // to skip a line
public String readLine() throws IOException {
while (lines.peek() == null) {
cbuf.clear();
Java8Compatibility.clear(cbuf);
// The default implementation of Reader#read(CharBuffer) allocates a
// temporary char[], so we call Reader#read(char[], int, int) instead.
int read = (reader != null) ? reader.read(buf, 0, buf.length) : readable.read(cbuf);
Expand Down
14 changes: 7 additions & 7 deletions android/guava/src/com/google/common/io/ReaderInputStream.java
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ final class ReaderInputStream extends InputStream {
encoder.reset();

charBuffer = CharBuffer.allocate(bufferSize);
charBuffer.flip();
Java8Compatibility.flip(charBuffer);

byteBuffer = ByteBuffer.allocate(bufferSize);
}
Expand Down Expand Up @@ -143,7 +143,7 @@ public int read(byte[] b, int off, int len) throws IOException {
return (totalBytesRead > 0) ? totalBytesRead : -1;
}
draining = false;
byteBuffer.clear();
Java8Compatibility.clear(byteBuffer);
}

while (true) {
Expand Down Expand Up @@ -189,8 +189,8 @@ public int read(byte[] b, int off, int len) throws IOException {
private static CharBuffer grow(CharBuffer buf) {
char[] copy = Arrays.copyOf(buf.array(), buf.capacity() * 2);
CharBuffer bigger = CharBuffer.wrap(copy);
bigger.position(buf.position());
bigger.limit(buf.limit());
Java8Compatibility.position(bigger, buf.position());
Java8Compatibility.limit(bigger, buf.limit());
return bigger;
}

Expand All @@ -207,7 +207,7 @@ private void readMoreChars() throws IOException {
if (availableCapacity(charBuffer) == 0) {
if (charBuffer.position() > 0) {
// (2) There is room in the buffer. Move existing bytes to the beginning.
charBuffer.compact().flip();
Java8Compatibility.flip(charBuffer.compact());
} else {
// (3) Entire buffer is full, need bigger buffer.
charBuffer = grow(charBuffer);
Expand All @@ -220,7 +220,7 @@ private void readMoreChars() throws IOException {
if (numChars == -1) {
endOfInput = true;
} else {
charBuffer.limit(limit + numChars);
Java8Compatibility.limit(charBuffer, limit + numChars);
}
}

Expand All @@ -235,7 +235,7 @@ private static int availableCapacity(Buffer buffer) {
* overflow must be due to a small output buffer.
*/
private void startDraining(boolean overflow) {
byteBuffer.flip();
Java8Compatibility.flip(byteBuffer);
if (overflow && byteBuffer.remaining() == 0) {
byteBuffer = ByteBuffer.allocate(byteBuffer.capacity() * 2);
} else {
Expand Down
4 changes: 2 additions & 2 deletions guava/src/com/google/common/hash/AbstractByteHasher.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ protected void update(byte[] b, int off, int len) {
protected void update(ByteBuffer b) {
if (b.hasArray()) {
update(b.array(), b.arrayOffset() + b.position(), b.remaining());
b.position(b.limit());
Java8Compatibility.position(b, b.limit());
} else {
for (int remaining = b.remaining(); remaining > 0; remaining--) {
update(b.get());
Expand All @@ -67,7 +67,7 @@ private Hasher update(int bytes) {
try {
update(scratch.array(), 0, bytes);
} finally {
scratch.clear();
Java8Compatibility.clear(scratch);
}
return this;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ public Hasher putBytes(byte[] bytes, int off, int len) {
public Hasher putBytes(ByteBuffer bytes) {
int pos = bytes.position();
for (Hasher hasher : hashers) {
bytes.position(pos);
Java8Compatibility.position(bytes, pos);
hasher.putBytes(bytes);
}
return this;
Expand Down
2 changes: 1 addition & 1 deletion guava/src/com/google/common/hash/AbstractHasher.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public Hasher putBytes(byte[] bytes, int off, int len) {
public Hasher putBytes(ByteBuffer b) {
if (b.hasArray()) {
putBytes(b.array(), b.arrayOffset() + b.position(), b.remaining());
b.position(b.limit());
Java8Compatibility.position(b, b.limit());
} else {
for (int remaining = b.remaining(); remaining > 0; remaining--) {
putByte(b.get());
Expand Down
14 changes: 7 additions & 7 deletions guava/src/com/google/common/hash/AbstractStreamingHasher.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,13 @@ protected AbstractStreamingHasher(int chunkSize, int bufferSize) {
* <p>This implementation simply pads with zeros and delegates to {@link #process(ByteBuffer)}.
*/
protected void processRemaining(ByteBuffer bb) {
bb.position(bb.limit()); // move at the end
bb.limit(chunkSize + 7); // get ready to pad with longs
Java8Compatibility.position(bb, bb.limit()); // move at the end
Java8Compatibility.limit(bb, chunkSize + 7); // get ready to pad with longs
while (bb.position() < chunkSize) {
bb.putLong(0);
}
bb.limit(chunkSize);
bb.flip();
Java8Compatibility.limit(bb, chunkSize);
Java8Compatibility.flip(bb);
process(bb);
}

Expand Down Expand Up @@ -179,10 +179,10 @@ public final Hasher putLong(long l) {
@Override
public final HashCode hash() {
munch();
buffer.flip();
Java8Compatibility.flip(buffer);
if (buffer.remaining() > 0) {
processRemaining(buffer);
buffer.position(buffer.limit());
Java8Compatibility.position(buffer, buffer.limit());
}
return makeHash();
}
Expand All @@ -203,7 +203,7 @@ private void munchIfFull() {
}

private void munch() {
buffer.flip();
Java8Compatibility.flip(buffer);
while (buffer.remaining() >= chunkSize) {
// we could limit the buffer to ensure process() does not read more than
// chunkSize number of bytes, but we trust the implementations
Expand Down
43 changes: 43 additions & 0 deletions guava/src/com/google/common/hash/Java8Compatibility.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright (C) 2020 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/

package com.google.common.hash;

import com.google.common.annotations.GwtIncompatible;
import java.nio.Buffer;

/**
* Wrappers around {@link Buffer} methods that are covariantly overridden in Java 9+. See
* https://github.com/google/guava/issues/3990
*/
@GwtIncompatible
final class Java8Compatibility {
static void clear(Buffer b) {
b.clear();
}

static void flip(Buffer b) {
b.flip();
}

static void limit(Buffer b, int limit) {
b.limit(limit);
}

static void position(Buffer b, int position) {
b.position(position);
}

private Java8Compatibility() {}
}
4 changes: 2 additions & 2 deletions guava/src/com/google/common/io/ByteStreams.java
Original file line number Diff line number Diff line change
Expand Up @@ -145,11 +145,11 @@ public static long copy(ReadableByteChannel from, WritableByteChannel to) throws
ByteBuffer buf = ByteBuffer.wrap(createBuffer());
long total = 0;
while (from.read(buf) != -1) {
buf.flip();
Java8Compatibility.flip(buf);
while (buf.hasRemaining()) {
total += to.write(buf);
}
buf.clear();
Java8Compatibility.clear(buf);
}
return total;
}
Expand Down
Loading

0 comments on commit 406a4ea

Please sign in to comment.