Skip to content

Commit

Permalink
Properly target Java 8
Browse files Browse the repository at this point in the history
Java 9+ added an overload of various methods in ByteBuffer. When compiling with Java 11+ and targeting Java 8 bytecode
the resulting signatures are invalid for JDK 8, so accesses below result in NoSuchMethodError. Accessing the
methods through the interface class works around the problem.

Ideally, we'd use "javac --release 8", but that doesn't work because Unsafe is not available in the signature data
for that profile.
  • Loading branch information
martint committed Aug 12, 2021
1 parent 2c1391a commit 5e353d0
Show file tree
Hide file tree
Showing 11 changed files with 116 additions and 23 deletions.
9 changes: 7 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,14 @@ jobs:
java: ['8', '11', '15', '16']
steps:
- uses: actions/checkout@v1
- name: Setup JDK ${{ matrix.java }}
- name: Setup test JDK ${{ matrix.java }}
uses: actions/setup-java@v1
with:
java-version: ${{ matrix.java }}
- run: echo "test_java_home=$JAVA_HOME" >> $GITHUB_ENV
- name: Setup build JDK 16
uses: actions/setup-java@v1
with:
java-version: 16
- name: Maven Test
run: mvn install -B
run: mvn install -V -P ci -B -Dtest_java_home=${{ env.test_java_home }}
17 changes: 17 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -167,4 +167,21 @@
</plugins>
</pluginManagement>
</build>

<profiles>
<profile>
<id>ci</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<jvm>${test_java_home}/bin/java</jvm>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
10 changes: 9 additions & 1 deletion src/main/java/io/airlift/compress/lz4/Lz4Compressor.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

import io.airlift.compress.Compressor;

import java.nio.Buffer;
import java.nio.ByteBuffer;

import static io.airlift.compress.lz4.Lz4RawCompressor.MAX_TABLE_SIZE;
Expand Down Expand Up @@ -45,8 +46,15 @@ public int compress(byte[] input, int inputOffset, int inputLength, byte[] outpu
}

@Override
public void compress(ByteBuffer input, ByteBuffer output)
public void compress(ByteBuffer inputBuffer, ByteBuffer outputBuffer)
{
// Java 9+ added an overload of various methods in ByteBuffer. When compiling with Java 11+ and targeting Java 8 bytecode
// the resulting signatures are invalid for JDK 8, so accesses below result in NoSuchMethodError. Accessing the
// methods through the interface class works around the problem
// Sidenote: we can't target "javac --release 8" because Unsafe is not available in the signature data for that profile
Buffer input = inputBuffer;
Buffer output = outputBuffer;

Object inputBase;
long inputAddress;
long inputLimit;
Expand Down
10 changes: 9 additions & 1 deletion src/main/java/io/airlift/compress/lz4/Lz4Decompressor.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import io.airlift.compress.Decompressor;
import io.airlift.compress.MalformedInputException;

import java.nio.Buffer;
import java.nio.ByteBuffer;

import static io.airlift.compress.lz4.UnsafeUtil.getAddress;
Expand All @@ -37,9 +38,16 @@ public int decompress(byte[] input, int inputOffset, int inputLength, byte[] out
}

@Override
public void decompress(ByteBuffer input, ByteBuffer output)
public void decompress(ByteBuffer inputBuffer, ByteBuffer outputBuffer)
throws MalformedInputException
{
// Java 9+ added an overload of various methods in ByteBuffer. When compiling with Java 11+ and targeting Java 8 bytecode
// the resulting signatures are invalid for JDK 8, so accesses below result in NoSuchMethodError. Accessing the
// methods through the interface class works around the problem
// Sidenote: we can't target "javac --release 8" because Unsafe is not available in the signature data for that profile
Buffer input = inputBuffer;
Buffer output = outputBuffer;

Object inputBase;
long inputAddress;
long inputLimit;
Expand Down
10 changes: 9 additions & 1 deletion src/main/java/io/airlift/compress/lzo/LzoCompressor.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

import io.airlift.compress.Compressor;

import java.nio.Buffer;
import java.nio.ByteBuffer;

import static io.airlift.compress.lzo.LzoRawCompressor.MAX_TABLE_SIZE;
Expand Down Expand Up @@ -45,8 +46,15 @@ public int compress(byte[] input, int inputOffset, int inputLength, byte[] outpu
}

@Override
public void compress(ByteBuffer input, ByteBuffer output)
public void compress(ByteBuffer inputBuffer, ByteBuffer outputBuffer)
{
// Java 9+ added an overload of various methods in ByteBuffer. When compiling with Java 11+ and targeting Java 8 bytecode
// the resulting signatures are invalid for JDK 8, so accesses below result in NoSuchMethodError. Accessing the
// methods through the interface class works around the problem
// Sidenote: we can't target "javac --release 8" because Unsafe is not available in the signature data for that profile
Buffer input = inputBuffer;
Buffer output = outputBuffer;

Object inputBase;
long inputAddress;
long inputLimit;
Expand Down
10 changes: 9 additions & 1 deletion src/main/java/io/airlift/compress/lzo/LzoDecompressor.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import io.airlift.compress.Decompressor;
import io.airlift.compress.MalformedInputException;

import java.nio.Buffer;
import java.nio.ByteBuffer;

import static io.airlift.compress.lzo.UnsafeUtil.getAddress;
Expand All @@ -37,9 +38,16 @@ public int decompress(byte[] input, int inputOffset, int inputLength, byte[] out
}

@Override
public void decompress(ByteBuffer input, ByteBuffer output)
public void decompress(ByteBuffer inputBuffer, ByteBuffer outputBuffer)
throws MalformedInputException
{
// Java 9+ added an overload of various methods in ByteBuffer. When compiling with Java 11+ and targeting Java 8 bytecode
// the resulting signatures are invalid for JDK 8, so accesses below result in NoSuchMethodError. Accessing the
// methods through the interface class works around the problem
// Sidenote: we can't target "javac --release 8" because Unsafe is not available in the signature data for that profile
Buffer input = inputBuffer;
Buffer output = outputBuffer;

Object inputBase;
long inputAddress;
long inputLimit;
Expand Down
10 changes: 9 additions & 1 deletion src/main/java/io/airlift/compress/snappy/SnappyCompressor.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

import io.airlift.compress.Compressor;

import java.nio.Buffer;
import java.nio.ByteBuffer;

import static io.airlift.compress.snappy.UnsafeUtil.getAddress;
Expand Down Expand Up @@ -43,8 +44,15 @@ public int compress(byte[] input, int inputOffset, int inputLength, byte[] outpu
}

@Override
public void compress(ByteBuffer input, ByteBuffer output)
public void compress(ByteBuffer inputBuffer, ByteBuffer outputBuffer)
{
// Java 9+ added an overload of various methods in ByteBuffer. When compiling with Java 11+ and targeting Java 8 bytecode
// the resulting signatures are invalid for JDK 8, so accesses below result in NoSuchMethodError. Accessing the
// methods through the interface class works around the problem
// Sidenote: we can't target "javac --release 8" because Unsafe is not available in the signature data for that profile
Buffer input = inputBuffer;
Buffer output = outputBuffer;

Object inputBase;
long inputAddress;
long inputLimit;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import io.airlift.compress.Decompressor;
import io.airlift.compress.MalformedInputException;

import java.nio.Buffer;
import java.nio.ByteBuffer;

import static io.airlift.compress.snappy.UnsafeUtil.getAddress;
Expand Down Expand Up @@ -45,9 +46,16 @@ public int decompress(byte[] input, int inputOffset, int inputLength, byte[] out
}

@Override
public void decompress(ByteBuffer input, ByteBuffer output)
public void decompress(ByteBuffer inputBuffer, ByteBuffer outputBuffer)
throws MalformedInputException
{
// Java 9+ added an overload of various methods in ByteBuffer. When compiling with Java 11+ and targeting Java 8 bytecode
// the resulting signatures are invalid for JDK 8, so accesses below result in NoSuchMethodError. Accessing the
// methods through the interface class works around the problem
// Sidenote: we can't target "javac --release 8" because Unsafe is not available in the signature data for that profile
Buffer input = inputBuffer;
Buffer output = outputBuffer;

Object inputBase;
long inputAddress;
long inputLimit;
Expand Down
10 changes: 9 additions & 1 deletion src/main/java/io/airlift/compress/zstd/ZstdCompressor.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

import io.airlift.compress.Compressor;

import java.nio.Buffer;
import java.nio.ByteBuffer;

import static io.airlift.compress.zstd.Constants.MAX_BLOCK_SIZE;
Expand Down Expand Up @@ -46,8 +47,15 @@ public int compress(byte[] input, int inputOffset, int inputLength, byte[] outpu
}

@Override
public void compress(ByteBuffer input, ByteBuffer output)
public void compress(ByteBuffer inputBuffer, ByteBuffer outputBuffer)
{
// Java 9+ added an overload of various methods in ByteBuffer. When compiling with Java 11+ and targeting Java 8 bytecode
// the resulting signatures are invalid for JDK 8, so accesses below result in NoSuchMethodError. Accessing the
// methods through the interface class works around the problem
// Sidenote: we can't target "javac --release 8" because Unsafe is not available in the signature data for that profile
Buffer input = inputBuffer;
Buffer output = outputBuffer;

Object inputBase;
long inputAddress;
long inputLimit;
Expand Down
10 changes: 9 additions & 1 deletion src/main/java/io/airlift/compress/zstd/ZstdDecompressor.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import io.airlift.compress.Decompressor;
import io.airlift.compress.MalformedInputException;

import java.nio.Buffer;
import java.nio.ByteBuffer;

import static io.airlift.compress.zstd.UnsafeUtil.getAddress;
Expand All @@ -39,9 +40,16 @@ public int decompress(byte[] input, int inputOffset, int inputLength, byte[] out
}

@Override
public void decompress(ByteBuffer input, ByteBuffer output)
public void decompress(ByteBuffer inputBuffer, ByteBuffer outputBuffer)
throws MalformedInputException
{
// Java 9+ added an overload of various methods in ByteBuffer. When compiling with Java 11+ and targeting Java 8 bytecode
// the resulting signatures are invalid for JDK 8, so accesses below result in NoSuchMethodError. Accessing the
// methods through the interface class works around the problem
// Sidenote: we can't target "javac --release 8" because Unsafe is not available in the signature data for that profile
Buffer input = inputBuffer;
Buffer output = outputBuffer;

Object inputBase;
long inputAddress;
long inputLimit;
Expand Down
33 changes: 20 additions & 13 deletions src/test/java/io/airlift/compress/AbstractTestCompression.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import javax.inject.Inject;

import java.io.IOException;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
Expand Down Expand Up @@ -155,7 +156,7 @@ public void testDecompressByteBufferHeapToHeap(DataSet dataSet)
ByteBuffer uncompressed = ByteBuffer.allocate(uncompressedOriginal.length);

getDecompressor().decompress(compressed, uncompressed);
uncompressed.flip();
((Buffer) uncompressed).flip();

assertByteBufferEqual(ByteBuffer.wrap(uncompressedOriginal), uncompressed);
}
Expand All @@ -174,7 +175,7 @@ public void testDecompressByteBufferHeapToDirect(DataSet dataSet)
ByteBuffer uncompressed = ByteBuffer.allocateDirect(uncompressedOriginal.length);

getDecompressor().decompress(compressed, uncompressed);
uncompressed.flip();
((Buffer) uncompressed).flip();

assertByteBufferEqual(ByteBuffer.wrap(uncompressedOriginal), uncompressed);
}
Expand All @@ -193,7 +194,7 @@ public void testDecompressByteBufferDirectToHeap(DataSet dataSet)
ByteBuffer uncompressed = ByteBuffer.allocate(uncompressedOriginal.length);

getDecompressor().decompress(compressed, uncompressed);
uncompressed.flip();
((Buffer) uncompressed).flip();

assertByteBufferEqual(ByteBuffer.wrap(uncompressedOriginal), uncompressed);
}
Expand All @@ -212,7 +213,7 @@ public void testDecompressByteBufferDirectToDirect(DataSet dataSet)
ByteBuffer uncompressed = ByteBuffer.allocateDirect(uncompressedOriginal.length);

getDecompressor().decompress(compressed, uncompressed);
uncompressed.flip();
((Buffer) uncompressed).flip();

assertByteBufferEqual(ByteBuffer.wrap(uncompressedOriginal), uncompressed);
}
Expand Down Expand Up @@ -323,17 +324,17 @@ private void verifyCompressByteBuffer(Compressor compressor, ByteBuffer expected
if (expected.remaining() > 1) {
ByteBuffer duplicate = expected.duplicate();
duplicate.get(); // skip one byte
compressor.compress(duplicate, ByteBuffer.allocate(compressed.remaining()));
compressor.compress(duplicate, ByteBuffer.allocate(((Buffer) compressed).remaining()));
}

compressor.compress(expected.duplicate(), compressed);
compressed.flip();
((Buffer) compressed).flip();

ByteBuffer uncompressed = ByteBuffer.allocate(expected.remaining());
ByteBuffer uncompressed = ByteBuffer.allocate(((Buffer) expected).remaining());

// TODO: validate with "control" decompressor
getDecompressor().decompress(compressed, uncompressed);
uncompressed.flip();
((Buffer) uncompressed).flip();

assertByteBufferEqual(expected.duplicate(), uncompressed);
}
Expand Down Expand Up @@ -409,21 +410,27 @@ public static void assertByteArraysEqual(byte[] left, int leftOffset, int leftLe

private static void assertByteBufferEqual(ByteBuffer left, ByteBuffer right)
{
int leftPosition = left.position();
int rightPosition = right.position();
for (int i = 0; i < Math.min(left.remaining(), right.remaining()); i++) {
Buffer leftBuffer = left;
Buffer rightBuffer = right;

int leftPosition = leftBuffer.position();
int rightPosition = rightBuffer.position();
for (int i = 0; i < Math.min(leftBuffer.remaining(), rightBuffer.remaining()); i++) {
if (left.get(leftPosition + i) != right.get(rightPosition + i)) {
fail(String.format("Byte buffers differ at position %s: 0x%02X vs 0x%02X", i, left.get(leftPosition + i), right.get(rightPosition + i)));
}
}

assertEquals(left.remaining(), right.remaining(), String.format("Buffer lengths differ: %s vs %s", left.remaining(), left.remaining()));
assertEquals(leftBuffer.remaining(), rightBuffer.remaining(), String.format("Buffer lengths differ: %s vs %s", leftBuffer.remaining(), leftBuffer.remaining()));
}

private static ByteBuffer toDirectBuffer(byte[] data)
{
ByteBuffer direct = ByteBuffer.allocateDirect(data.length);
direct.put(data).flip();
direct.put(data);

((Buffer) direct).flip();

return direct;
}

Expand Down

0 comments on commit 5e353d0

Please sign in to comment.