Skip to content

Commit f0ce205

Browse files
authored
IGNITE-25525 ExceptionInInitializerError in BinaryTupleParser since JDK 17 (#5931)
1 parent e107428 commit f0ce205

File tree

8 files changed

+251
-95
lines changed

8 files changed

+251
-95
lines changed

modules/binary-tuple/src/main/java/org/apache/ignite/internal/binarytuple/BinaryTupleParser.java

Lines changed: 39 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@
2828
import java.time.LocalTime;
2929
import java.time.Period;
3030
import java.util.UUID;
31+
import java.util.function.Function;
3132
import org.apache.ignite.internal.util.ByteUtils;
32-
import org.apache.ignite.internal.util.GridUnsafe;
3333

3434
/**
3535
* Binary tuple parser allows to get bytes of individual elements from entirety of tuple bytes.
@@ -52,9 +52,6 @@ public interface Sink {
5252
/** Byte order of ByteBuffers that contain the tuple. */
5353
public static final ByteOrder ORDER = ByteOrder.LITTLE_ENDIAN;
5454

55-
/** Whether the byte order of the underlying buffer is reversed compared to the native byte order. */
56-
private static final boolean REVERSE_BYTE_ORDER = GridUnsafe.NATIVE_BYTE_ORDER != ORDER;
57-
5855
/** UUID size in bytes. */
5956
private static final int UUID_SIZE = 16;
6057

@@ -75,19 +72,29 @@ public interface Sink {
7572
/** Binary tuple. */
7673
protected final ByteBuffer buffer;
7774

75+
/**
76+
* This constructor uses a default `PlainByteBufferAccessor` for accessing the buffer.
77+
*
78+
* @param numElements The number of elements in the binary tuple.
79+
* @param buffer The `ByteBuffer` containing the binary tuple data.
80+
*/
81+
public BinaryTupleParser(int numElements, ByteBuffer buffer) {
82+
this(numElements, buffer, PlainByteBufferAccessor::new);
83+
}
84+
7885
/**
7986
* Constructor.
8087
*
8188
* @param numElements Number of tuple elements.
8289
* @param buffer Buffer with a binary tuple.
8390
*/
84-
public BinaryTupleParser(int numElements, ByteBuffer buffer) {
91+
public BinaryTupleParser(int numElements, ByteBuffer buffer, Function<ByteBuffer, ByteBufferAccessor> byteBufferAccessorFactory) {
8592
this.numElements = numElements;
8693

8794
assert buffer.order() == ORDER : "Buffer order must be LITTLE_ENDIAN, actual: " + buffer.order();
8895
assert buffer.position() == 0 : "Buffer position must be 0, actual: " + buffer.position();
8996
this.buffer = buffer;
90-
byteBufferAccessor = new ByteBufferAccessor(buffer);
97+
byteBufferAccessor = byteBufferAccessorFactory.apply(buffer);
9198

9299
byte flags = byteBufferAccessor.get(0);
93100

@@ -658,107 +665,49 @@ private LocalTime getTime(int offset, int length) {
658665
}
659666

660667
/**
661-
* An interface for accessing a byte buffer with methods to read various data types
662-
* at specific positions. This interface abstracts the underlying implementation
663-
* for handling data in either direct or heap-based byte buffers.
668+
* A plain implementation of the `ByteBufferAccessor` interface.
669+
* This class provides methods to access various data types from a `ByteBuffer`.
664670
*/
665-
public static class ByteBufferAccessor {
666-
private final byte[] bytes;
667-
private final long addr;
668-
private final int capacity;
669-
670-
ByteBufferAccessor(ByteBuffer buff) {
671-
if (buff.isDirect()) {
672-
bytes = null;
673-
addr = GridUnsafe.bufferAddress(buff);
674-
} else {
675-
bytes = buff.array();
676-
addr = GridUnsafe.BYTE_ARR_OFF + buff.arrayOffset();
677-
}
671+
private static class PlainByteBufferAccessor implements ByteBufferAccessor {
672+
private final ByteBuffer buffer;
678673

679-
capacity = buff.capacity();
674+
PlainByteBufferAccessor(ByteBuffer buffer) {
675+
this.buffer = buffer;
680676
}
681677

682-
/**
683-
* Retrieves the byte value from the underlying byte buffer at the specified index.
684-
*
685-
* @param p the index in the underlying byte buffer to retrieve the byte from.
686-
* @return the byte value located at the specified index in the byte buffer.
687-
*/
688-
public byte get(int p) {
689-
return GridUnsafe.getByte(bytes, addr + p);
678+
@Override
679+
public byte get(int index) {
680+
return buffer.get(index);
690681
}
691682

692-
/**
693-
* Reads a 32-bit integer value from the underlying byte buffer at the specified index.
694-
*
695-
* @param p the index in the underlying byte buffer to start reading the 32-bit integer value from.
696-
* @return the 32-bit integer value located at the specified index in the byte buffer.
697-
*/
698-
public int getInt(int p) {
699-
int value = GridUnsafe.getInt(bytes, addr + p);
700-
701-
return REVERSE_BYTE_ORDER ? Integer.reverseBytes(value) : value;
683+
@Override
684+
public short getShort(int index) {
685+
return buffer.getShort(index);
702686
}
703687

704-
/**
705-
* Reads a 64-bit long value from the underlying byte buffer at the specified index.
706-
*
707-
* @param p the index in the underlying byte buffer to start reading the 64-bit long value from.
708-
* @return the 64-bit long value located at the specified index in the byte buffer.
709-
*/
710-
public long getLong(int p) {
711-
long value = GridUnsafe.getLong(bytes, addr + p);
712-
713-
return REVERSE_BYTE_ORDER ? Long.reverseBytes(value) : value;
688+
@Override
689+
public int getInt(int index) {
690+
return buffer.getInt(index);
714691
}
715692

716-
/**
717-
* Reads a 16-bit short value from the underlying byte buffer at the specified index.
718-
*
719-
* @param p the index in the underlying byte buffer to start reading the 16-bit short value from.
720-
* @return the 16-bit short value located at the specified index in the byte buffer.
721-
*/
722-
public short getShort(int p) {
723-
short value = GridUnsafe.getShort(bytes, addr + p);
724-
725-
return REVERSE_BYTE_ORDER ? Short.reverseBytes(value) : value;
693+
@Override
694+
public long getLong(int index) {
695+
return buffer.getLong(index);
726696
}
727697

728-
/**
729-
* Reads a 32-bit floating-point value from the underlying byte buffer at the specified index.
730-
*
731-
* @param p the index in the underlying byte buffer to start reading the 32-bit floating-point value from.
732-
* @return the 32-bit floating-point value located at the specified index in the byte buffer.
733-
*/
734-
public float getFloat(int p) {
735-
float value = GridUnsafe.getFloat(bytes, addr + p);
736-
737-
return REVERSE_BYTE_ORDER ? Float.intBitsToFloat(Integer.reverseBytes(Float.floatToIntBits(value))) : value;
698+
@Override
699+
public float getFloat(int index) {
700+
return buffer.getFloat(index);
738701
}
739702

740-
/**
741-
* Reads a 64-bit double-precision floating-point value from the underlying
742-
* byte buffer at the specified index.
743-
*
744-
* @param p the index in the underlying byte buffer to start reading the
745-
* 64-bit double-precision floating-point value from.
746-
* @return the 64-bit double-precision floating-point value located at
747-
* the specified index in the byte buffer.
748-
*/
749-
public double getDouble(int p) {
750-
double value = GridUnsafe.getDouble(bytes, addr + p);
751-
752-
return REVERSE_BYTE_ORDER ? Double.longBitsToDouble(Long.reverseBytes(Double.doubleToLongBits(value))) : value;
703+
@Override
704+
public double getDouble(int index) {
705+
return buffer.getDouble(index);
753706
}
754707

755-
/**
756-
* Returns the capacity of the underlying byte buffer, representing the total number of bytes it can hold.
757-
*
758-
* @return the total capacity of the byte buffer.
759-
*/
708+
@Override
760709
public int capacity() {
761-
return capacity;
710+
return buffer.capacity();
762711
}
763712
}
764713
}

modules/binary-tuple/src/main/java/org/apache/ignite/internal/binarytuple/BinaryTupleReader.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import java.time.LocalTime;
2929
import java.time.Period;
3030
import java.util.UUID;
31+
import java.util.function.Function;
3132
import org.jetbrains.annotations.Nullable;
3233

3334
/**
@@ -60,6 +61,17 @@ public BinaryTupleReader(int numElements, ByteBuffer buffer) {
6061
super(numElements, buffer);
6162
}
6263

64+
/**
65+
* Constructor with a specific factory function for creating a `ByteBufferAccessor`.
66+
*
67+
* @param numElements Number of tuple elements.
68+
* @param buffer Buffer with a binary tuple.
69+
* @param byteBufferAccessorFactory A factory function to create a `ByteBufferAccessor` for accessing the buffer.
70+
*/
71+
public BinaryTupleReader(int numElements, ByteBuffer buffer, Function<ByteBuffer, ByteBufferAccessor> byteBufferAccessorFactory) {
72+
super(numElements, buffer, byteBufferAccessorFactory);
73+
}
74+
6375
/** {@inheritDoc} */
6476
@Override
6577
public final void nextElement(int index, int begin, int end) {
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.ignite.internal.binarytuple;
19+
20+
/**
21+
* An interface for accessing a byte buffer with methods to read various data types
22+
* at specific positions. This interface abstracts the underlying implementation
23+
* for handling data in either direct or heap-based byte buffers.
24+
*/
25+
public interface ByteBufferAccessor {
26+
/**
27+
* Retrieves the byte value from the underlying byte buffer at the specified index.
28+
*
29+
* @param p the index in the underlying byte buffer to retrieve the byte from.
30+
* @return the byte value located at the specified index in the byte buffer.
31+
*/
32+
byte get(int p);
33+
34+
/**
35+
* Reads a 32-bit integer value from the underlying byte buffer at the specified index.
36+
*
37+
* @param p the index in the underlying byte buffer to start reading the 32-bit integer value from.
38+
* @return the 32-bit integer value located at the specified index in the byte buffer.
39+
*/
40+
int getInt(int p);
41+
42+
/**
43+
* Reads a 64-bit long value from the underlying byte buffer at the specified index.
44+
*
45+
* @param p the index in the underlying byte buffer to start reading the 64-bit long value from.
46+
* @return the 64-bit long value located at the specified index in the byte buffer.
47+
*/
48+
long getLong(int p);
49+
50+
/**
51+
* Reads a 16-bit short value from the underlying byte buffer at the specified index.
52+
*
53+
* @param p the index in the underlying byte buffer to start reading the 16-bit short value from.
54+
* @return the 16-bit short value located at the specified index in the byte buffer.
55+
*/
56+
short getShort(int p);
57+
58+
/**
59+
* Reads a 32-bit floating-point value from the underlying byte buffer at the specified index.
60+
*
61+
* @param p the index in the underlying byte buffer to start reading the 32-bit floating-point value from.
62+
* @return the 32-bit floating-point value located at the specified index in the byte buffer.
63+
*/
64+
float getFloat(int p);
65+
66+
/**
67+
* Reads a 64-bit double-precision floating-point value from the underlying
68+
* byte buffer at the specified index.
69+
*
70+
* @param p the index in the underlying byte buffer to start reading the
71+
* 64-bit double-precision floating-point value from.
72+
* @return the 64-bit double-precision floating-point value located at
73+
* the specified index in the byte buffer.
74+
*/
75+
double getDouble(int p);
76+
77+
/**
78+
* Returns the capacity of the underlying byte buffer, representing the total number of bytes it can hold.
79+
*
80+
* @return the total capacity of the byte buffer.
81+
*/
82+
int capacity();
83+
}

modules/schema/src/main/java/org/apache/ignite/internal/schema/BinaryTuple.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@
1818
package org.apache.ignite.internal.schema;
1919

2020
import java.nio.ByteBuffer;
21+
import java.util.function.Function;
2122
import org.apache.ignite.internal.binarytuple.BinaryTupleBuilder;
2223
import org.apache.ignite.internal.binarytuple.BinaryTupleReader;
24+
import org.apache.ignite.internal.binarytuple.ByteBufferAccessor;
2325

2426
/**
2527
* Utility for access to binary tuple elements as typed values and with schema knowledge that allows to read
@@ -46,6 +48,17 @@ public BinaryTuple(int elementCount, ByteBuffer buffer) {
4648
super(elementCount, buffer);
4749
}
4850

51+
/**
52+
* Constructor with a specific factory function for creating a `ByteBufferAccessor`.
53+
*
54+
* @param elementCount Number of tuple elements.
55+
* @param buffer Buffer with a binary tuple.
56+
* @param accessorFactory A factory function to create a `ByteBufferAccessor` for accessing the buffer.
57+
*/
58+
public BinaryTuple(int elementCount, ByteBuffer buffer, Function<ByteBuffer, ByteBufferAccessor> accessorFactory) {
59+
super(elementCount, buffer, accessorFactory);
60+
}
61+
4962
@Override
5063
public void copyValue(BinaryTupleBuilder builder, int columnIndex) {
5164
copyRawValue(builder, columnIndex);

modules/schema/src/main/java/org/apache/ignite/internal/schema/BinaryTupleComparator.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,10 @@ public int compare(ByteBuffer buffer1, ByteBuffer buffer2) {
6666

6767
int numElements = columnTypes.size();
6868

69-
BinaryTupleReader tuple1 = isBuffer1Prefix ? new BinaryTuplePrefix(numElements, buffer1) : new BinaryTuple(numElements, buffer1);
70-
BinaryTupleReader tuple2 = isBuffer2Prefix ? new BinaryTuplePrefix(numElements, buffer2) : new BinaryTuple(numElements, buffer2);
69+
BinaryTupleReader tuple1 = isBuffer1Prefix ? new BinaryTuplePrefix(numElements, buffer1)
70+
: new BinaryTuple(numElements, buffer1, UnsafeByteBufferAccessor::new);
71+
BinaryTupleReader tuple2 = isBuffer2Prefix ? new BinaryTuplePrefix(numElements, buffer2)
72+
: new BinaryTuple(numElements, buffer2, UnsafeByteBufferAccessor::new);
7173

7274
int columnsToCompare = Math.min(tuple1.elementCount(), tuple2.elementCount());
7375

modules/schema/src/main/java/org/apache/ignite/internal/schema/BinaryTupleComparatorUtils.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@
2424
import java.math.BigDecimal;
2525
import java.nio.ByteBuffer;
2626
import org.apache.ignite.internal.binarytuple.BinaryTupleCommon;
27-
import org.apache.ignite.internal.binarytuple.BinaryTupleParser.ByteBufferAccessor;
2827
import org.apache.ignite.internal.binarytuple.BinaryTupleReader;
28+
import org.apache.ignite.internal.binarytuple.ByteBufferAccessor;
2929
import org.apache.ignite.sql.ColumnType;
3030

3131
/**

modules/schema/src/main/java/org/apache/ignite/internal/schema/PartialBinaryTupleMatcher.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,10 @@ public int match(ByteBuffer buffer1, ByteBuffer buffer2) {
8484

8585
assert !isBuffer1Prefix : "An inline tuple must not contain a prefix.";
8686

87-
BinaryTupleReader tuple1 = new BinaryTuple(numElements, buffer1);
87+
BinaryTupleReader tuple1 = new BinaryTuple(numElements, buffer1, UnsafeByteBufferAccessor::new);
8888

89-
BinaryTupleReader tuple2 = isBuffer2Prefix ? new BinaryTuplePrefix(numElements, buffer2) : new BinaryTuple(numElements, buffer2);
89+
BinaryTupleReader tuple2 = isBuffer2Prefix ? new BinaryTuplePrefix(numElements, buffer2)
90+
: new BinaryTuple(numElements, buffer2, UnsafeByteBufferAccessor::new);
9091

9192
int columnsToCompare = Math.min(tuple1.elementCount(), tuple2.elementCount());
9293

0 commit comments

Comments
 (0)