Cast ByteBuffer to Buffer before calling position()
Change-Id: Id1405e5a3e8bb0dee201ba9a604c6af12a27cb14
diff --git a/src/main/java/com/android/tools/r8/code/InstructionFactory.java b/src/main/java/com/android/tools/r8/code/InstructionFactory.java
index 14d2f4b..83b0570 100644
--- a/src/main/java/com/android/tools/r8/code/InstructionFactory.java
+++ b/src/main/java/com/android/tools/r8/code/InstructionFactory.java
@@ -4,7 +4,6 @@
package com.android.tools.r8.code;
import com.android.tools.r8.graph.OffsetToObjectMapping;
-import java.nio.ByteBuffer;
import java.nio.ShortBuffer;
import java.util.ArrayList;
import java.util.List;
@@ -18,11 +17,6 @@
return create(high, opcode, stream, mapping);
}
- public Instruction[] readSequenceFrom(ByteBuffer buffer, int startIndex, int length,
- OffsetToObjectMapping mapping) {
- return readSequenceFrom(buffer.asShortBuffer(), startIndex, length, mapping);
- }
-
public Instruction[] readSequenceFrom(ShortBuffer buffer, int startIndex, int length,
OffsetToObjectMapping mapping) {
ShortBufferBytecodeStream range =
diff --git a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
index 825846e..26398d8 100644
--- a/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/ApplicationWriter.java
@@ -281,7 +281,7 @@
}
// Release use of the backing buffer now that accept has returned.
data.invalidate();
- byteBufferProvider.releaseByteBuffer(result.buffer);
+ byteBufferProvider.releaseByteBuffer(result.buffer.asByteBuffer());
return true;
}));
}
diff --git a/src/main/java/com/android/tools/r8/dex/BinaryReader.java b/src/main/java/com/android/tools/r8/dex/BinaryReader.java
index 5d51238..dd1cfee 100644
--- a/src/main/java/com/android/tools/r8/dex/BinaryReader.java
+++ b/src/main/java/com/android/tools/r8/dex/BinaryReader.java
@@ -10,14 +10,13 @@
import com.android.tools.r8.utils.LebUtils;
import com.android.tools.r8.utils.StreamUtils;
import java.io.IOException;
-import java.nio.ByteBuffer;
/**
* Base class for reading binary content.
*/
public abstract class BinaryReader {
protected final Origin origin;
- protected final ByteBuffer buffer;
+ protected final CompatByteBuffer buffer;
protected BinaryReader(ProgramResource resource) throws ResourceException, IOException {
this(resource.getOrigin(), StreamUtils.StreamToByteArrayClose(resource.getByteStream()));
@@ -26,7 +25,7 @@
protected BinaryReader(Origin origin, byte[] bytes) {
assert origin != null;
this.origin = origin;
- buffer = ByteBuffer.wrap(bytes);
+ buffer = CompatByteBuffer.wrap(bytes);
}
public Origin getOrigin() {
diff --git a/src/main/java/com/android/tools/r8/dex/CompatByteBuffer.java b/src/main/java/com/android/tools/r8/dex/CompatByteBuffer.java
new file mode 100644
index 0000000..6e32c6e
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/dex/CompatByteBuffer.java
@@ -0,0 +1,135 @@
+// Copyright (c) 2019, the R8 project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+package com.android.tools.r8.dex;
+
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.ShortBuffer;
+
+/**
+ * In JDK 9 ByteBuffer ByteBuffer.position(int) started overriding Buffer Buffer.position(int) along
+ * with various other methods defined on java.nio.Buffer. To avoid issues with running R8 on JDK 8
+ * we internally wrap any use of ByteBuffer and make sure access to the overridden methods happens
+ * only at the super type Buffer which is known to be in both JDKs.
+ */
+public class CompatByteBuffer {
+
+ private final ByteBuffer buffer;
+
+ public CompatByteBuffer(ByteBuffer buffer) {
+ this.buffer = buffer;
+ }
+
+ public static CompatByteBuffer wrap(byte[] bytes) {
+ return new CompatByteBuffer(ByteBuffer.wrap(bytes));
+ }
+
+ private Buffer asBuffer() {
+ return buffer;
+ }
+
+ public ByteBuffer asByteBuffer() {
+ return buffer;
+ }
+
+ // ----------------------------------------------------------------------------------------------
+ // 1.8 compatible calls to java.nio.Buffer methods.
+ // ----------------------------------------------------------------------------------------------
+
+ // The position(int) became overridden with a ByteBuffer return value.
+ public void position(int newPosition) {
+ asBuffer().position(newPosition);
+ }
+
+ // The rewind() became overridden with a ByteBuffer return value.
+ public void rewind() {
+ asBuffer().rewind();
+ }
+
+ // ----------------------------------------------------------------------------------------------
+ // Methods on java.nio.Buffer that are safely overridden or not non-overridden.
+ // ----------------------------------------------------------------------------------------------
+
+ // Note: array() overrides Buffer.array() in JDK 8 too, so that is safe for JDK 8 and 9.
+ public byte[] array() {
+ return asByteBuffer().array();
+ }
+
+ public int arrayOffset() {
+ return asByteBuffer().arrayOffset();
+ }
+
+ public int capacity() {
+ return asByteBuffer().capacity();
+ }
+
+ public boolean hasArray() {
+ return asByteBuffer().hasArray();
+ }
+
+ public boolean hasRemaining() {
+ return asByteBuffer().hasRemaining();
+ }
+
+ public int position() {
+ return asByteBuffer().position();
+ }
+
+ public int remaining() {
+ return asByteBuffer().remaining();
+ }
+
+ // ----------------------------------------------------------------------------------------------
+ // Methods on java.nio.ByteBuffer.
+ // ----------------------------------------------------------------------------------------------
+
+ public ShortBuffer asShortBuffer() {
+ return asByteBuffer().asShortBuffer();
+ }
+
+ public void order(ByteOrder bo) {
+ asByteBuffer().order(bo);
+ }
+
+ public byte get() {
+ return asByteBuffer().get();
+ }
+
+ public byte get(int index) {
+ return asByteBuffer().get(index);
+ }
+
+ public void get(byte[] dst) {
+ asByteBuffer().get(dst);
+ }
+
+ public int getInt() {
+ return asByteBuffer().getInt();
+ }
+
+ public int getInt(int offset) {
+ return asByteBuffer().getInt(offset);
+ }
+
+ public short getShort() {
+ return asByteBuffer().getShort();
+ }
+
+ public void put(byte aByte) {
+ asByteBuffer().put(aByte);
+ }
+
+ public void putShort(short aShort) {
+ asByteBuffer().putShort(aShort);
+ }
+
+ public void putInt(int anInteger) {
+ asByteBuffer().putInt(anInteger);
+ }
+
+ public void put(byte[] bytes) {
+ asByteBuffer().put(bytes);
+ }
+}
diff --git a/src/main/java/com/android/tools/r8/dex/DexOutputBuffer.java b/src/main/java/com/android/tools/r8/dex/DexOutputBuffer.java
index 000bc0e..2d1da51 100644
--- a/src/main/java/com/android/tools/r8/dex/DexOutputBuffer.java
+++ b/src/main/java/com/android/tools/r8/dex/DexOutputBuffer.java
@@ -22,7 +22,7 @@
private static final int DEFAULT_BUFFER_SIZE = 256 * 1024;
private final ByteBufferProvider byteBufferProvider;
- private ByteBuffer byteBuffer;
+ private CompatByteBuffer byteBuffer;
@VisibleForTesting
DexOutputBuffer() {
@@ -37,16 +37,16 @@
private void ensureSpaceFor(int bytes) {
if (byteBuffer.remaining() < bytes) {
int newSize = byteBuffer.capacity() + Math.max(byteBuffer.capacity(), bytes * 2);
- ByteBuffer newBuffer = allocateByteBuffer(newSize);
- System.arraycopy(byteBuffer.array(), 0, newBuffer.array(), 0, byteBuffer.position());
+ CompatByteBuffer newBuffer = allocateByteBuffer(newSize);
+ System.arraycopy(byteBuffer.array(), 0, newBuffer.array(), 0, position());
newBuffer.position(byteBuffer.position());
freeByteBuffer(byteBuffer);
byteBuffer = newBuffer;
}
}
- private ByteBuffer allocateByteBuffer(int size) {
- ByteBuffer buffer = byteBufferProvider.acquireByteBuffer(size);
+ private CompatByteBuffer allocateByteBuffer(int size) {
+ CompatByteBuffer buffer = new CompatByteBuffer(byteBufferProvider.acquireByteBuffer(size));
if (!buffer.hasArray()) {
throw new CompilationError(
"Provided byte-buffer is required to have an array backing, but does not.");
@@ -69,9 +69,9 @@
return buffer;
}
- private void freeByteBuffer(ByteBuffer buffer) {
+ private void freeByteBuffer(CompatByteBuffer buffer) {
assert buffer != null;
- byteBufferProvider.releaseByteBuffer(buffer);
+ byteBufferProvider.releaseByteBuffer(buffer.asByteBuffer());
}
public void putUleb128(int value) {
@@ -133,7 +133,7 @@
public int align(int bytes) {
assert bytes > 0;
int mask = bytes - 1;
- int newPosition = (byteBuffer.position() + mask) & ~mask;
+ int newPosition = (position() + mask) & ~mask;
ensureSpaceFor(newPosition - position());
byteBuffer.position(newPosition);
return newPosition;
@@ -165,8 +165,8 @@
return byteBuffer.array();
}
- public ByteBuffer stealByteBuffer() {
- ByteBuffer buffer = byteBuffer;
+ public CompatByteBuffer stealByteBuffer() {
+ CompatByteBuffer buffer = byteBuffer;
byteBuffer = null;
return buffer;
}
diff --git a/src/main/java/com/android/tools/r8/dex/DexReader.java b/src/main/java/com/android/tools/r8/dex/DexReader.java
index d8997f7..45a0696 100644
--- a/src/main/java/com/android/tools/r8/dex/DexReader.java
+++ b/src/main/java/com/android/tools/r8/dex/DexReader.java
@@ -12,7 +12,6 @@
import com.android.tools.r8.utils.DexVersion;
import java.io.IOException;
import java.nio.BufferUnderflowException;
-import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/**
@@ -38,7 +37,7 @@
}
// Parse the magic header and determine the dex file version.
- private int parseMagic(ByteBuffer buffer) {
+ private int parseMagic(CompatByteBuffer buffer) {
try {
buffer.get();
buffer.rewind();
diff --git a/src/main/java/com/android/tools/r8/dex/FileWriter.java b/src/main/java/com/android/tools/r8/dex/FileWriter.java
index 1af80fa..4197da5 100644
--- a/src/main/java/com/android/tools/r8/dex/FileWriter.java
+++ b/src/main/java/com/android/tools/r8/dex/FileWriter.java
@@ -57,7 +57,6 @@
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Reference2IntLinkedOpenHashMap;
import it.unimi.dsi.fastutil.objects.Reference2IntMap;
-import java.nio.ByteBuffer;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.Collection;
@@ -77,10 +76,10 @@
/** Simple pair of a byte buffer and its written length. */
public static class ByteBufferResult {
// Ownership of the buffer is transferred to the receiver of this result structure.
- public final ByteBuffer buffer;
+ public final CompatByteBuffer buffer;
public final int length;
- private ByteBufferResult(ByteBuffer buffer, int length) {
+ private ByteBufferResult(CompatByteBuffer buffer, int length) {
this.buffer = buffer;
this.length = length;
}
diff --git a/src/main/java/com/android/tools/r8/dex/VDexReader.java b/src/main/java/com/android/tools/r8/dex/VDexReader.java
index a3a5a2f..8d6f2d0 100644
--- a/src/main/java/com/android/tools/r8/dex/VDexReader.java
+++ b/src/main/java/com/android/tools/r8/dex/VDexReader.java
@@ -14,7 +14,6 @@
import com.google.common.io.ByteStreams;
import java.io.IOException;
import java.io.InputStream;
-import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/**
@@ -37,7 +36,7 @@
}
// Parse the magic header and determine the dex file version.
- private int parseMagic(ByteBuffer buffer) {
+ private int parseMagic(CompatByteBuffer buffer) {
int index = 0;
for (byte prefixByte : VDEX_FILE_MAGIC_PREFIX) {
if (buffer.get(index++) != prefixByte) {
diff --git a/src/test/java/com/android/tools/r8/code/InstructionFactoryTest.java b/src/test/java/com/android/tools/r8/code/InstructionFactoryTest.java
index ddd4f69..a1cfe7b 100644
--- a/src/test/java/com/android/tools/r8/code/InstructionFactoryTest.java
+++ b/src/test/java/com/android/tools/r8/code/InstructionFactoryTest.java
@@ -19,7 +19,7 @@
ByteBuffer emptyBuffer = ByteBuffer.allocate(0);
InstructionFactory factory = new InstructionFactory();
Instruction[] instructions =
- factory.readSequenceFrom(emptyBuffer, 0, 0, new OffsetToObjectMapping());
+ factory.readSequenceFrom(emptyBuffer.asShortBuffer(), 0, 0, new OffsetToObjectMapping());
assertTrue(instructions.length == 0);
}
}