outOfBandBuffers)
return bindingThreadLocal.get().get().deserialize(bytes, outOfBandBuffers);
}
+ @NotForAndroid(reason = "Android does not support support off-heap memory only by address")
@Override
public Object deserialize(long address, int size) {
return bindingThreadLocal.get().get().deserialize(address, size);
@@ -159,7 +161,7 @@ public Object deserialize(MemoryBuffer buffer) {
@Override
public Object deserialize(ByteBuffer byteBuffer) {
- return bindingThreadLocal.get().get().deserialize(MemoryUtils.wrap(byteBuffer));
+ return bindingThreadLocal.get().get().deserialize(MemoryBuffer.wrap(byteBuffer));
}
@Override
diff --git a/java/fory-core/src/main/java/org/apache/fory/annotation/NotForAndroid.java b/java/fory-core/src/main/java/org/apache/fory/annotation/NotForAndroid.java
new file mode 100644
index 0000000000..3805f7106d
--- /dev/null
+++ b/java/fory-core/src/main/java/org/apache/fory/annotation/NotForAndroid.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.fory.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.CLASS)
+@Target({
+ ElementType.METHOD,
+ ElementType.CONSTRUCTOR,
+ ElementType.TYPE,
+})
+public @interface NotForAndroid {
+ String reason() default "This API is not supported or is unsafe on the Android platform.";
+}
diff --git a/java/fory-core/src/main/java/org/apache/fory/annotation/PartialAndroidSupport.java b/java/fory-core/src/main/java/org/apache/fory/annotation/PartialAndroidSupport.java
new file mode 100644
index 0000000000..8e0c587c63
--- /dev/null
+++ b/java/fory-core/src/main/java/org/apache/fory/annotation/PartialAndroidSupport.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.fory.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Documented
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.TYPE})
+public @interface PartialAndroidSupport {
+
+ int minApiLevel() default -1;
+
+ String reason() default "该方法在 Android 上的所有分支和条件下不保证完全支持,请查阅文档或源码。";
+
+ String docUrl() default "";
+}
diff --git a/java/fory-core/src/main/java/org/apache/fory/io/AbstractStreamReader.java b/java/fory-core/src/main/java/org/apache/fory/io/AbstractStreamReader.java
index 81a63280b0..f695ab244a 100644
--- a/java/fory-core/src/main/java/org/apache/fory/io/AbstractStreamReader.java
+++ b/java/fory-core/src/main/java/org/apache/fory/io/AbstractStreamReader.java
@@ -32,9 +32,6 @@ public int fillBuffer(int minFillSize) {
@Override
public void readTo(byte[] dst, int dstIndex, int length) {}
- @Override
- public void readToUnsafe(Object target, long targetPointer, int numBytes) {}
-
@Override
public void readToByteBuffer(ByteBuffer dst, int length) {}
diff --git a/java/fory-core/src/main/java/org/apache/fory/io/ForyInputStream.java b/java/fory-core/src/main/java/org/apache/fory/io/ForyInputStream.java
index 93dbd77b7e..a487b2f63d 100644
--- a/java/fory-core/src/main/java/org/apache/fory/io/ForyInputStream.java
+++ b/java/fory-core/src/main/java/org/apache/fory/io/ForyInputStream.java
@@ -24,7 +24,6 @@
import java.nio.ByteBuffer;
import javax.annotation.concurrent.NotThreadSafe;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.Platform;
/**
* A buffered stream by fory. Do not use original {@link InputStream} when this stream object
@@ -45,7 +44,7 @@ public ForyInputStream(InputStream stream, int bufferSize) {
this.stream = stream;
this.bufferSize = bufferSize;
byte[] bytes = new byte[bufferSize];
- this.buffer = MemoryBuffer.fromByteArray(bytes, 0, 0, this);
+ this.buffer = new MemoryBuffer(bytes, 0, 0, this);
}
@Override
@@ -115,18 +114,50 @@ public void readTo(byte[] dst, int dstIndex, int len) {
}
}
- @Override
- public void readToUnsafe(Object target, long targetPointer, int numBytes) {
- MemoryBuffer buf = buffer;
- int remaining = buf.remaining();
- if (remaining < numBytes) {
- fillBuffer(numBytes - remaining);
- }
- byte[] heapMemory = buf.getHeapMemory();
- long address = buf.getUnsafeReaderAddress();
- Platform.copyMemory(heapMemory, address, target, targetPointer, numBytes);
- buf.increaseReaderIndex(numBytes);
- }
+ // @Override
+ // public void readCharsTo(char[] target, int offset, int length) {
+ // int numBytes = length * 2;
+ // MemoryBuffer buf = buffer;
+ // int remaining = buf.remaining();
+ // if (remaining < numBytes) {
+ // fillBuffer(numBytes - remaining);
+ // }
+ // buf.readCharsDirect(target, offset, length);
+ // }
+ //
+ // @Override
+ // public void readLongsTo(long[] target, int offset, int length) {
+ // int numBytes = length * 8;
+ // MemoryBuffer buf = buffer;
+ // int remaining = buf.remaining();
+ // if (remaining < numBytes) {
+ // fillBuffer(numBytes - remaining);
+ // }
+ // buf.readLongsDirect(target, offset, length);
+ // }
+ //
+ // @Override
+ // public void readBoolsTo(boolean[] target, int offset, int length) {
+ // MemoryBuffer buf = buffer;
+ // int remaining = buf.remaining();
+ // if (remaining < length) {
+ // fillBuffer(length - remaining);
+ // }
+ // buf.readBoolsDirect(target, offset, length);
+ // }
+
+ // @Override
+ // public void readToUnsafe(Object target, long targetPointer, int numBytes) {
+ // MemoryBuffer buf = buffer;
+ // int remaining = buf.remaining();
+ // if (remaining < numBytes) {
+ // fillBuffer(numBytes - remaining);
+ // }
+ // byte[] heapMemory = buf.getHeapMemory();
+ // long address = buf.getUnsafeReaderAddress();
+ // Platform.copyMemory(heapMemory, address, target, targetPointer, numBytes);
+ // buf.increaseReaderIndex(numBytes);
+ // }
@Override
public void readToByteBuffer(ByteBuffer dst, int length) {
diff --git a/java/fory-core/src/main/java/org/apache/fory/io/ForyReadableChannel.java b/java/fory-core/src/main/java/org/apache/fory/io/ForyReadableChannel.java
index 1afbcbf7b3..d3157bd915 100644
--- a/java/fory-core/src/main/java/org/apache/fory/io/ForyReadableChannel.java
+++ b/java/fory-core/src/main/java/org/apache/fory/io/ForyReadableChannel.java
@@ -24,9 +24,7 @@
import java.nio.channels.ReadableByteChannel;
import javax.annotation.concurrent.NotThreadSafe;
import org.apache.fory.exception.DeserializationException;
-import org.apache.fory.memory.ByteBufferUtil;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.Platform;
import org.apache.fory.util.Preconditions;
@NotThreadSafe
@@ -63,7 +61,7 @@ public int fillBuffer(int minFillSize) {
byteBuf.position(0);
newByteBuf.put(byteBuf);
byteBuf = byteBuffer = newByteBuf;
- memoryBuf.initDirectBuffer(ByteBufferUtil.getAddress(byteBuf), position, byteBuf);
+ memoryBuf.initDirectBuffer(byteBuf, newSize);
}
byteBuf.limit(newLimit);
int readCount = channel.read(byteBuf);
@@ -105,17 +103,49 @@ public void readTo(byte[] dst, int dstIndex, int length) {
}
}
- @Override
- public void readToUnsafe(Object target, long targetPointer, int numBytes) {
- MemoryBuffer buf = memoryBuffer;
- int remaining = buf.remaining();
- if (remaining < numBytes) {
- fillBuffer(numBytes - remaining);
- }
- long address = buf.getUnsafeReaderAddress();
- Platform.copyMemory(null, address, target, targetPointer, numBytes);
- buf.increaseReaderIndex(numBytes);
- }
+ // @Override
+ // public void readCharsTo(char[] target, int offset, int length) {
+ // int numBytes = length * 2;
+ // MemoryBuffer buf = memoryBuffer;
+ // int remaining = buf.remaining();
+ // if (remaining < numBytes) {
+ // fillBuffer(numBytes - remaining);
+ // }
+ // buf.readCharsDirect(target, offset, length);
+ // }
+ //
+ // @Override
+ // public void readLongsTo(long[] target, int offset, int length) {
+ // int numBytes = length * 8;
+ // MemoryBuffer buf = memoryBuffer;
+ // int remaining = buf.remaining();
+ // if (remaining < numBytes) {
+ // fillBuffer(numBytes - remaining);
+ // }
+ // buf.readLongsDirect(target, offset, length);
+ // }
+ //
+ // @Override
+ // public void readBoolsTo(boolean[] target, int offset, int length) {
+ // MemoryBuffer buf = memoryBuffer;
+ // int remaining = buf.remaining();
+ // if (remaining < length) {
+ // fillBuffer(length - remaining);
+ // }
+ // buf.readBoolsDirect(target, offset, length);
+ // }
+
+ // @Override
+ // public void readToUnsafe(Object target, long targetPointer, int numBytes) {
+ // MemoryBuffer buf = memoryBuffer;
+ // int remaining = buf.remaining();
+ // if (remaining < numBytes) {
+ // fillBuffer(numBytes - remaining);
+ // }
+ // long address = buf.getUnsafeReaderAddress();
+ // Platform.copyMemory(null, address, target, targetPointer, numBytes);
+ // buf.increaseReaderIndex(numBytes);
+ // }
@Override
public void readToByteBuffer(ByteBuffer dst, int length) {
diff --git a/java/fory-core/src/main/java/org/apache/fory/io/ForyStreamReader.java b/java/fory-core/src/main/java/org/apache/fory/io/ForyStreamReader.java
index 352abef9b2..ff1a811fe5 100644
--- a/java/fory-core/src/main/java/org/apache/fory/io/ForyStreamReader.java
+++ b/java/fory-core/src/main/java/org/apache/fory/io/ForyStreamReader.java
@@ -42,7 +42,14 @@ public interface ForyStreamReader {
* Read data into `target`. This method will block until the enough data are written into the
* `target`.
*/
- void readToUnsafe(Object target, long targetPointer, int numBytes);
+
+ // void readCharsTo(char[] target, int offset, int length);
+ //
+ // void readLongsTo(long[] target, int offset, int length);
+ //
+ // void readBoolsTo(boolean[] target, int offset, int length);
+ //
+ // void readToUnsafe(Object target, long targetPointer, int numBytes);
/**
* Read data into `dst`. This method will block until the enough data are written into the `dst`.
diff --git a/java/fory-core/src/main/java/org/apache/fory/memory/BufferPool.java b/java/fory-core/src/main/java/org/apache/fory/memory/BufferPool.java
new file mode 100644
index 0000000000..ab4ba352f8
--- /dev/null
+++ b/java/fory-core/src/main/java/org/apache/fory/memory/BufferPool.java
@@ -0,0 +1,180 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 org.apache.fory.memory;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentLinkedDeque;
+
+/**
+ * A global, non-blocking, thread-safe byte array buffer pool.
+ *
+ * This class provides direct access to pooled {@code byte[]} arrays to minimize allocation
+ * overhead and GC pressure in high-performance applications.
+ *
+ *
WARNING: This is a low-level utility. The consumer is solely responsible for
+ * returning the borrowed buffer by calling {@link #release(byte[])} in a {@code finally} block.
+ * Failure to do so will result in a buffer leak, eventually exhausting the pool.
+ */
+public final class BufferPool {
+
+ /** Singleton instance for global access. */
+ public static final BufferPool INSTANCE = new BufferPool();
+
+ /**
+ * Defines the pooling strategy (buffer size -> number of buffers). This map is made unmodifiable
+ * for safety.
+ */
+ private static final Map POOL_CONFIG;
+
+ static {
+ // This static initializer block is compatible with all Java versions, including Java 8.
+ Map config = new HashMap<>();
+ // These sizes are chosen based on common network packet sizes and memory page alignment.
+ config.put(512, 10);
+ config.put(1024, 6);
+ config.put(2048, 4); // 1KB, for small messages
+ config.put(3072, 2); // 4KB, common page size
+ config.put(4096, 1); // 16KB, for medium data chunks
+ POOL_CONFIG = Collections.unmodifiableMap(config);
+ }
+
+ /**
+ * The core data structure of the pool. Key: The size of the buffer arrays in a tier. Value: A
+ * thread-safe queue holding the available buffers for that size.
+ */
+ private final Map> pool;
+
+ /**
+ * An array of the available buffer sizes, sorted in ascending order. This is used for efficient
+ * lookup of the appropriate buffer tier.
+ */
+ private final int[] bufferSizes;
+
+ /** Private constructor to enforce singleton pattern and initialize the pool. */
+ private BufferPool() {
+ this.pool = new ConcurrentHashMap<>();
+
+ // Initialize the sorted array of buffer sizes for fast lookups.
+ this.bufferSizes = POOL_CONFIG.keySet().stream().mapToInt(Integer::intValue).sorted().toArray();
+
+ // Pre-allocate all buffers and populate the pool.
+ for (int size : bufferSizes) {
+ ConcurrentLinkedDeque queue = new ConcurrentLinkedDeque<>();
+ int count = POOL_CONFIG.get(size);
+ for (int i = 0; i < count; i++) {
+ queue.offer(new byte[size]);
+ }
+ this.pool.put(size, queue);
+ }
+ }
+
+ /**
+ * Borrows a {@code byte[]} from the pool, only searching for buffers large enough to satisfy the
+ * request.
+ *
+ * @param requiredSize The minimum required capacity of the buffer in bytes.
+ * @return An {@link Optional} containing a {@code byte[]}, or an empty Optional if no suitable
+ * buffer is available.
+ */
+ public byte[] borrow(int requiredSize) {
+ return borrow(requiredSize, false);
+ }
+
+ /**
+ * Borrows a {@code byte[]} from the pool with extended search options.
+ *
+ * This is a non-blocking method. It first attempts to find the smallest available buffer that
+ * is greater than or equal to the required size. If no such buffer is found and {@code
+ * acceptSmaller} is true, it will then search downwards from the largest tier to find any
+ * available buffer.
+ *
+ * @param requiredSize The minimum required capacity of the buffer in bytes.
+ * @param acceptSmaller If true, the method will return a smaller buffer if no suitable large
+ * buffer is found.
+ * @return An {@link Optional} containing a {@code byte[]}, or an empty Optional if the pool is
+ * exhausted.
+ */
+ public byte[] borrow(int requiredSize, boolean acceptSmaller) {
+ // Use binary search to find the smallest suitable buffer tier.
+ int searchResult = Arrays.binarySearch(bufferSizes, requiredSize);
+ int startIndex = (searchResult >= 0) ? searchResult : (-(searchResult + 1));
+
+ // First, iterate upwards from the best-fit size to find a suitable buffer.
+ for (int i = startIndex; i < bufferSizes.length; i++) {
+ int size = bufferSizes[i];
+ ConcurrentLinkedDeque queue = pool.get(size);
+ byte[] buffer = queue.poll(); // poll() is non-blocking.
+ if (buffer != null) {
+ return buffer;
+ }
+ }
+ // If no suitable large buffer was found and the user accepts a smaller one...
+ if (acceptSmaller) {
+ // ...iterate downwards from the largest tier to find any available buffer.
+ for (int i = bufferSizes.length - 1; i >= 0; i--) {
+ int size = bufferSizes[i];
+ ConcurrentLinkedDeque queue = pool.get(size);
+ byte[] buffer = queue.poll();
+ if (buffer != null) {
+ return buffer;
+ }
+ }
+ }
+ // All suitable pools are empty, or the requested size is larger than any available tier.
+ return null;
+ }
+
+ /**
+ * Returns a borrowed {@code byte[]} to the pool.
+ *
+ * It is critical for the consumer to call this method for every buffer borrowed to prevent
+ * pool leaks.
+ *
+ * @param buffer The byte array to return to the pool. It must be an array that was previously
+ * borrowed from this pool.
+ */
+ public void release(byte[] buffer) {
+ if (buffer == null) {
+ return;
+ }
+ int size = buffer.length;
+ ConcurrentLinkedDeque queue = pool.get(size);
+ if (queue != null) {
+ queue.offer(buffer);
+ }
+ // Note: In a production system, returning a buffer of an unknown size
+ // might be logged to a proper logging framework. Here, we silently ignore it
+ // for maximum performance.
+ }
+
+ /** Provides statistics about the current state of the pool for monitoring or debugging. */
+ public void printStats() {
+ System.out.println("--- BufferPool Stats ---");
+ for (int size : bufferSizes) {
+ System.out.printf("Tier Size %5d B: %d available%n", size, pool.get(size).size());
+ }
+ System.out.println("------------------------");
+ }
+}
diff --git a/java/fory-core/src/main/java/org/apache/fory/memory/ByteBufferUtil.java b/java/fory-core/src/main/java/org/apache/fory/memory/ByteBufferUtil.java
index c78cd08cb6..dbbc7fae92 100644
--- a/java/fory-core/src/main/java/org/apache/fory/memory/ByteBufferUtil.java
+++ b/java/fory-core/src/main/java/org/apache/fory/memory/ByteBufferUtil.java
@@ -22,6 +22,7 @@
import java.lang.reflect.Field;
import java.nio.Buffer;
import java.nio.ByteBuffer;
+import org.apache.fory.annotation.NotForAndroid;
import org.apache.fory.util.Preconditions;
public class ByteBufferUtil {
@@ -33,9 +34,14 @@ public class ByteBufferUtil {
Field addressField = Buffer.class.getDeclaredField("address");
BUFFER_ADDRESS_FIELD_OFFSET = Platform.objectFieldOffset(addressField);
Preconditions.checkArgument(BUFFER_ADDRESS_FIELD_OFFSET != 0);
- Field capacityField = Buffer.class.getDeclaredField("capacity");
- BUFFER_CAPACITY_FIELD_OFFSET = Platform.objectFieldOffset(capacityField);
- Preconditions.checkArgument(BUFFER_CAPACITY_FIELD_OFFSET != 0);
+ if (Platform.IS_ANDROID) {
+ BUFFER_CAPACITY_FIELD_OFFSET = -1;
+ } else {
+ Field capacityField =
+ Buffer.class.getDeclaredField("capacity"); // Android does not support this field
+ BUFFER_CAPACITY_FIELD_OFFSET = Platform.objectFieldOffset(capacityField);
+ Preconditions.checkArgument(BUFFER_CAPACITY_FIELD_OFFSET != 0);
+ }
} catch (NoSuchFieldException e) {
throw new IllegalStateException(e);
}
@@ -56,6 +62,7 @@ public static long getAddress(ByteBuffer buffer) {
private static final ByteBuffer localBuffer = ByteBuffer.allocateDirect(0);
/** Create a direct buffer from native memory represented by address [address, address + size). */
+ @NotForAndroid(reason = "Android cannot directly operate the capacity field")
public static ByteBuffer createDirectByteBufferFromNativeAddress(long address, int size) {
try {
// ByteBuffer.allocateDirect(0) is about 30x slower than `localBuffer.duplicate()`.
@@ -69,21 +76,13 @@ public static ByteBuffer createDirectByteBufferFromNativeAddress(long address, i
}
}
- /** Wrap a buffer [address, address + size) into provided buffer. */
- public static void wrapDirectByteBufferFromNativeAddress(
- ByteBuffer buffer, long address, int size) {
- Preconditions.checkArgument(
- buffer.isDirect(), "Can't wrap native memory into a non-direct ByteBuffer.");
- Platform.putLong(buffer, BUFFER_ADDRESS_FIELD_OFFSET, address);
- Platform.putInt(buffer, BUFFER_CAPACITY_FIELD_OFFSET, size);
- buffer.clear();
- }
-
+ @NotForAndroid
public static ByteBuffer wrapDirectBuffer(long address, int size) {
return createDirectByteBufferFromNativeAddress(address, size);
}
/** Wrap a buffer [address, address + size) into provided buffer. */
+ @NotForAndroid(reason = "Android cannot directly operate the capacity field")
public static void wrapDirectBuffer(ByteBuffer buffer, long address, int size) {
Platform.putLong(buffer, BUFFER_ADDRESS_FIELD_OFFSET, address);
Platform.putInt(buffer, BUFFER_CAPACITY_FIELD_OFFSET, size);
@@ -101,8 +100,4 @@ public static void flipBuffer(Buffer buffer) {
public static void rewind(Buffer buffer) {
buffer.rewind();
}
-
- public static void position(Buffer buffer, int pos) {
- buffer.position(pos);
- }
}
diff --git a/java/fory-core/src/main/java/org/apache/fory/memory/MemoryBuffer.java b/java/fory-core/src/main/java/org/apache/fory/memory/MemoryBuffer.java
index ae35d16334..835bf6af07 100644
--- a/java/fory-core/src/main/java/org/apache/fory/memory/MemoryBuffer.java
+++ b/java/fory-core/src/main/java/org/apache/fory/memory/MemoryBuffer.java
@@ -21,11 +21,14 @@
import static org.apache.fory.util.Preconditions.checkArgument;
import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
import java.util.Arrays;
+import javax.naming.OperationNotSupportedException;
import org.apache.fory.annotation.CodegenInvoke;
+import org.apache.fory.annotation.NotForAndroid;
+import org.apache.fory.annotation.PartialAndroidSupport;
import org.apache.fory.io.AbstractStreamReader;
import org.apache.fory.io.ForyStreamReader;
+import org.apache.fory.type.Types;
import sun.misc.Unsafe;
/**
@@ -60,9 +63,12 @@
* DesiredMethodLimit,MaxRecursiveInlineLevel,FreqInlineSize,MaxInlineSize
*/
public final class MemoryBuffer {
+ public static final int BOOLEAN_TRANSFER_THRESHOLD = 512;
public static final int BUFFER_GROW_STEP_THRESHOLD = 100 * 1024 * 1024;
private static final Unsafe UNSAFE = Platform.UNSAFE;
- private static final boolean LITTLE_ENDIAN = (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN);
+ private static final boolean LITTLE_ENDIAN = Platform.IS_LITTLE_ENDIAN;
+
+ private final boolean onHeap;
// If the data in on the heap, `heapMemory` will be non-null, and its' the object relative to
// which we access the memory.
@@ -70,15 +76,22 @@ public final class MemoryBuffer {
// to undefined addresses outside the heap and may in out-of-order execution cases cause
// buffer faults.
private byte[] heapMemory;
- private int heapOffset;
- // If the data is off the heap, `offHeapBuffer` will be non-null, and it's the direct byte buffer
- // that allocated on the off-heap memory.
- // This memory buffer holds a reference to that buffer, so as long as this memory buffer lives,
- // the memory will not be released.
- private ByteBuffer offHeapBuffer;
+
+ // the offset in the heap memory byte array, i.e. the relative offset to the // `heapMemory` byte
+ // array.
+ // 注意当是 off-heap时,这个是一开始传入时buffer的position
+ // 如果是 on-heap, 这个是一开始传入数组的offset
+ private int memoryOffset; // 用于记录为相对于最底层的内存的偏移(忽略中间任何切片)
+
+ // represents the both off-heap and on-heap memory.
+ private ByteBuffer buffer;
+
// The readable/writeable range is [address, addressLimit).
// If the data in on the heap, this is the relative offset to the `heapMemory` byte array.
// If the data is off the heap, this is the absolute memory address.
+ // 注意,当是off-heap, 这个是是算上一开始传入时buffer的position的
+ // 当是heap,Platform.BYTE_ARRAY_OFFSET + 一开始传入数组的offset
+ // 用于代表第一个可以(允许读取的字节,onHeap: Platform._ARRAY_OFFSET + elementOffset, offHeap: address + position)
private long address;
// The address one byte after the last addressable byte, i.e. `address + size` while the
// buffer is not disposed.
@@ -97,7 +110,7 @@ public final class MemoryBuffer {
* array.length.
* @param length buffer size
*/
- private MemoryBuffer(byte[] buffer, int offset, int length) {
+ public MemoryBuffer(byte[] buffer, int offset, int length) {
this(buffer, offset, length, null);
}
@@ -110,12 +123,13 @@ private MemoryBuffer(byte[] buffer, int offset, int length) {
* @param length buffer size
* @param streamReader a reader for reading from a stream.
*/
- private MemoryBuffer(byte[] buffer, int offset, int length, ForyStreamReader streamReader) {
+ public MemoryBuffer(byte[] buffer, int offset, int length, ForyStreamReader streamReader) {
checkArgument(offset >= 0 && length >= 0);
if (offset + length > buffer.length) {
throw new IllegalArgumentException(
String.format("%d exceeds buffer size %d", offset + length, buffer.length));
}
+ this.onHeap = true;
initHeapBuffer(buffer, offset, length);
if (streamReader != null) {
this.streamReader = streamReader;
@@ -128,55 +142,78 @@ private MemoryBuffer(byte[] buffer, int offset, int length, ForyStreamReader str
* Creates a new memory buffer that represents the native memory at the absolute address given by
* the pointer.
*
- * @param offHeapAddress The address of the memory represented by this memory buffer.
- * @param size The size of this memory buffer.
* @param offHeapBuffer The byte buffer whose memory is represented by this memory buffer which
* may be null if the memory is not allocated by `DirectByteBuffer`. Hold this buffer to avoid
* the memory being released.
+ * @param length The size of this memory buffer.
+ * @param streamReader a reader for reading from a stream.
*/
- private MemoryBuffer(long offHeapAddress, int size, ByteBuffer offHeapBuffer) {
- this(offHeapAddress, size, offHeapBuffer, null);
+ private MemoryBuffer(
+ long offHeapAddress,
+ ByteBuffer offHeapBuffer,
+ int length,
+ ForyStreamReader streamReader,
+ boolean useBufferObject) {
+ assert (offHeapAddress == -1 && offHeapBuffer != null)
+ || (offHeapAddress != -1 && offHeapBuffer == null);
+ this.onHeap = false;
+ initDirectBuffer(offHeapAddress, offHeapBuffer, length, useBufferObject);
+ if (streamReader != null) {
+ this.streamReader = streamReader;
+ } else {
+ this.streamReader = new BoundChecker();
+ }
}
/**
* Creates a new memory buffer that represents the native memory at the absolute address given by
* the pointer.
*
- * @param offHeapAddress The address of the memory represented by this memory buffer.
- * @param size The size of this memory buffer.
+ * @param length The size of this memory buffer.
* @param offHeapBuffer The byte buffer whose memory is represented by this memory buffer which
* may be null if the memory is not allocated by `DirectByteBuffer`. Hold this buffer to avoid
* the memory being released.
- * @param streamReader a reader for reading from a stream.
*/
- private MemoryBuffer(
- long offHeapAddress, int size, ByteBuffer offHeapBuffer, ForyStreamReader streamReader) {
- initDirectBuffer(offHeapAddress, size, offHeapBuffer);
- if (streamReader != null) {
- this.streamReader = streamReader;
- } else {
- this.streamReader = new BoundChecker();
- }
+ public void initDirectBuffer(ByteBuffer offHeapBuffer, int length) {
+ initDirectBuffer(-1, offHeapBuffer, length, false);
}
- public void initDirectBuffer(long offHeapAddress, int size, ByteBuffer offHeapBuffer) {
- this.offHeapBuffer = offHeapBuffer;
- if (offHeapAddress <= 0) {
+ private void initDirectBuffer(
+ long offHeapAddress, ByteBuffer offHeapBuffer, int length, boolean useBufferObject) {
+ assert (offHeapAddress == -1 && offHeapBuffer != null)
+ || (offHeapAddress != -1 && offHeapBuffer == null);
+ if (offHeapBuffer == null && Platform.IS_ANDROID) {
+ Platform.throwException(
+ new OperationNotSupportedException(
+ "Android does not support off-heap memory only by address, use ByteBuffer instead"));
+ }
+ if (offHeapBuffer != null) {
+ if (useBufferObject) {
+ this.buffer = offHeapBuffer; // 不进行slice, 直接使用传入的buffer对象
+ } else {
+ this.buffer =
+ offHeapBuffer.slice().order(Platform.NATIVE_BYTE_ORDER); // 先slice再order, 防止影响到参数buffer
+ }
+ this.address =
+ ByteBufferUtil.getAddress(this.buffer); // 注意要用被赋值的this.buffer而不是参数offHeapBuffer
+ this.buffer.limit(length);
+ } else {
+ this.address = offHeapAddress;
+ }
+ if (this.address <= 0) {
throw new IllegalArgumentException("negative pointer or size");
}
- if (offHeapAddress >= Long.MAX_VALUE - Integer.MAX_VALUE) {
+ if (this.address >= Long.MAX_VALUE - Integer.MAX_VALUE) {
// this is necessary to make sure the collapsed checks are safe against numeric overflows
throw new IllegalArgumentException(
"Buffer initialized with too large address: "
- + offHeapAddress
+ + this.address
+ " ; Max allowed address is "
+ (Long.MAX_VALUE - Integer.MAX_VALUE - 1));
}
-
this.heapMemory = null;
- this.address = offHeapAddress;
+ this.size = length;
this.addressLimit = this.address + size;
- this.size = size;
}
private class BoundChecker extends AbstractStreamReader {
@@ -194,16 +231,18 @@ public MemoryBuffer getBuffer() {
}
}
- public void initHeapBuffer(byte[] buffer, int offset, int length) {
- if (buffer == null) {
+ public void initHeapBuffer(byte[] bytes, int offset, int length) {
+ if (bytes == null) {
throw new NullPointerException("buffer");
}
- this.heapMemory = buffer;
- this.heapOffset = offset;
+ this.heapMemory = bytes;
+ this.memoryOffset = offset;
final long startPos = Platform.BYTE_ARRAY_OFFSET + offset;
this.address = startPos;
this.size = length;
this.addressLimit = startPos + length;
+ // 若不进行slice(), 则ByteBuffer[offset=0, pos = offset], 切片后ByteBuffer[offset=offset, pos=0]
+ this.buffer = ByteBuffer.wrap(bytes, offset, length).slice().order(Platform.NATIVE_BYTE_ORDER);
}
// ------------------------------------------------------------------------
@@ -223,22 +262,12 @@ public void increaseSize(int diff) {
this.addressLimit = address + (size += diff);
}
- /**
- * Checks whether this memory buffer is backed by off-heap memory.
- *
- * @return true, if the memory buffer is backed by off-heap memory, false if it
- * is backed by heap memory.
- */
- public boolean isOffHeap() {
- return heapMemory == null;
- }
-
/**
* Returns true, if the memory buffer is backed by heap memory and memory buffer can
* write to the whole memory region of underlying byte array.
*/
public boolean isHeapFullyWriteable() {
- return heapMemory != null && heapOffset == 0;
+ return heapMemory != null && memoryOffset == 0;
}
/**
@@ -256,12 +285,8 @@ public byte[] getHeapMemory() {
*
* @return The byte buffer that owns the memory of this memory buffer.
*/
- public ByteBuffer getOffHeapBuffer() {
- if (offHeapBuffer != null) {
- return offHeapBuffer;
- } else {
- throw new IllegalStateException("Memory buffer does not represent off heap ByteBuffer");
- }
+ public ByteBuffer getInnerBuffer() {
+ return buffer;
}
/**
@@ -285,7 +310,7 @@ public byte[] getArray() {
* @throws IllegalStateException if the memory buffer does not represent off-heap memory
*/
public long getAddress() {
- if (heapMemory == null) {
+ if (!onHeap) {
return address;
} else {
throw new IllegalStateException("Memory buffer does not represent off heap memory");
@@ -308,15 +333,11 @@ private void checkPosition(long index, long pos, long length) {
}
}
- public void get(int index, byte[] dst) {
- get(index, dst, 0, dst.length);
- }
-
public void get(int index, byte[] dst, int offset, int length) {
final byte[] heapMemory = this.heapMemory;
if (heapMemory != null) {
// System.arraycopy faster for some jdk than Unsafe.
- System.arraycopy(heapMemory, heapOffset + index, dst, offset, length);
+ System.arraycopy(heapMemory, memoryOffset + index, dst, offset, length);
} else {
final long pos = address + index;
if ((index
@@ -328,10 +349,11 @@ public void get(int index, byte[] dst, int offset, int length) {
< 0) {
throwOOBException();
}
- Platform.copyMemory(null, pos, dst, Platform.BYTE_ARRAY_OFFSET + offset, length);
+ copyTo(index, dst, offset, length, Types.JavaArray.BYTE, false);
}
}
+ @SuppressWarnings("deprecation")
public void get(int offset, ByteBuffer target, int numBytes) {
if ((offset | numBytes | (offset + numBytes)) < 0) {
throwOOBException();
@@ -344,18 +366,27 @@ public void get(int offset, ByteBuffer target, int numBytes) {
}
final int targetPos = target.position();
if (target.isDirect()) {
+ final long sourceOffset = address + offset;
+ if (sourceOffset > addressLimit - numBytes) {
+ throwOOBException();
+ }
final long targetAddr = ByteBufferUtil.getAddress(target) + targetPos;
- final long sourceAddr = address + offset;
- if (sourceAddr <= addressLimit - numBytes) {
- Platform.copyMemory(heapMemory, sourceAddr, null, targetAddr, numBytes);
+ if (Platform.IS_ANDROID) {
+ if (onHeap) {
+ target.put(heapMemory, memoryOffset + offset, numBytes); // 此操作会改变target的position,无需再调整了
+ return;
+ } else {
+ // Android只支持这个三个参数的copyMemory
+ Platform.UNSAFE.copyMemory(sourceOffset, targetAddr, numBytes);
+ }
} else {
- throwOOBException();
+ Platform.copyMemory(heapMemory, sourceOffset, null, targetAddr, numBytes);
}
} else {
assert target.hasArray();
get(offset, target.array(), targetPos + target.arrayOffset(), numBytes);
}
- ByteBufferUtil.position(target, targetPos + numBytes);
+ target.position(targetPos + numBytes);
}
public void put(int offset, ByteBuffer source, int numBytes) {
@@ -367,16 +398,24 @@ public void put(int offset, ByteBuffer source, int numBytes) {
if (source.isDirect()) {
final long sourceAddr = ByteBufferUtil.getAddress(source) + sourcePos;
final long targetAddr = address + offset;
- if (targetAddr <= addressLimit - numBytes) {
- Platform.copyMemory(null, sourceAddr, heapMemory, targetAddr, numBytes);
- } else {
+ if (targetAddr > addressLimit - numBytes) {
throwOOBException();
}
+ if (Platform.IS_ANDROID) {
+ if (onHeap) {
+ source.get(heapMemory, memoryOffset + offset, numBytes); // 此操作会改变source的position,无需再调整了
+ return;
+ }
+ // Android只支持这个三个参数的copyMemory
+ Platform.UNSAFE.copyMemory(sourceAddr, targetAddr, numBytes);
+ } else {
+ Platform.copyMemory(null, sourceAddr, heapMemory, targetAddr, numBytes);
+ }
} else {
assert source.hasArray();
put(offset, source.array(), sourcePos + source.arrayOffset(), numBytes);
}
- ByteBufferUtil.position(source, sourcePos + numBytes);
+ source.position(sourcePos + numBytes);
}
public void put(int index, byte[] src) {
@@ -387,7 +426,7 @@ public void put(int index, byte[] src, int offset, int length) {
final byte[] heapMemory = this.heapMemory;
if (heapMemory != null) {
// System.arraycopy faster for some jdk than Unsafe.
- System.arraycopy(src, offset, heapMemory, heapOffset + index, length);
+ System.arraycopy(src, offset, heapMemory, memoryOffset + index, length);
} else {
final long pos = address + index;
// check the byte array offset and length
@@ -400,8 +439,7 @@ public void put(int index, byte[] src, int offset, int length) {
< 0) {
throwOOBException();
}
- final long arrayAddress = Platform.BYTE_ARRAY_OFFSET + offset;
- Platform.copyMemory(src, arrayAddress, null, pos, length);
+ coverMemoryWithArray(index, src, offset, length, Types.JavaArray.BYTE, false);
}
}
@@ -613,7 +651,7 @@ public void _unsafeWriterIndex(int writerIndex) {
// CHECKSTYLE.OFF:MethodName
public int _unsafeHeapWriterIndex() {
// CHECKSTYLE.ON:MethodName
- return writerIndex + heapOffset;
+ return writerIndex + memoryOffset;
}
// CHECKSTYLE.OFF:MethodName
@@ -1203,31 +1241,133 @@ public void write(ByteBuffer source, int numBytes) {
writerIndex = newIdx;
}
+ /*--------------------------------------------------------------------------------*/
+ /**
+ * Writes a boolean array to the buffer using an optimized chunking strategy.
+ *
+ * For large arrays, it borrows a temporary byte buffer from a pool to convert booleans to
+ * bytes in chunks, minimizing method call overhead. For small arrays or if the pool is exhausted,
+ * it falls back to a simple, direct loop.
+ *
+ * @param arr The source boolean array.
+ * @param offset The starting offset in the source array.
+ * @param length The number of booleans to write.
+ */
+ // ByteBuffer需要在外部调整好position, 此函数不会移动writerIndex
+ private void coverMemoryWithBoolArrayInner(boolean[] arr, int offset, int length) {
+ // Fast Path: Use pooling and chunking for large arrays.
+ if (length >= BOOLEAN_TRANSFER_THRESHOLD) {
+ byte[] tmpBytes = BufferPool.INSTANCE.borrow(length, true);
+ // If borrowing was successful, proceed with the optimized path.
+ if (tmpBytes != null && tmpBytes.length >= BOOLEAN_TRANSFER_THRESHOLD / 3) {
+ int remaining = length;
+ int currentOffset = offset;
+ while (remaining > 0) {
+ int chunkSize = Math.min(remaining, tmpBytes.length);
+ for (int i = 0; i < chunkSize; i++) {
+ tmpBytes[i] = arr[currentOffset + i] ? (byte) 1 : (byte) 0;
+ }
+ buffer.put(tmpBytes, 0, chunkSize);
+ remaining -= chunkSize;
+ currentOffset += chunkSize;
+ }
+ BufferPool.INSTANCE.release(tmpBytes);
+ return;
+ }
+ }
+ // Fallback Path: For small arrays or if the buffer pool was exhausted.
+ int limit = offset + length;
+ for (int i = offset; i < limit; i++) {
+ buffer.put(arr[i] ? (byte) 1 : (byte) 0);
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ // 此函数不会自动扩容,在保证空间足够的情况下使用
+ public void coverMemoryWithArray(
+ int bufOffset,
+ Object arr,
+ int offset,
+ int length,
+ Types.JavaArray eleType,
+ boolean autoFill) {
+ boolean writeMode = bufOffset < 0;
+ if (writeMode) {
+ bufOffset = writerIndex;
+ }
+ int numBytes = length * eleType.bytesPerEle;
+ if (autoFill) {
+ ensure(bufOffset + numBytes);
+ }
+ if (eleType == Types.JavaArray.BYTE && onHeap) {
+ System.arraycopy(arr, offset, heapMemory, memoryOffset + bufOffset, numBytes);
+ } else {
+ if (!Platform.IS_ANDROID) {
+ Platform.copyMemory(
+ arr,
+ eleType.arrayMemOffset + (long) offset * eleType.bytesPerEle,
+ heapMemory,
+ address + bufOffset,
+ numBytes);
+ } else {
+ buffer.position(bufOffset);
+ switch (eleType) {
+ case BOOL:
+ coverMemoryWithBoolArrayInner((boolean[]) arr, offset, length);
+ break;
+ case BYTE:
+ buffer.put((byte[]) arr, offset, length);
+ break;
+ case CHAR:
+ buffer.asCharBuffer().put((char[]) arr, offset, length);
+ break;
+ case SHORT:
+ buffer.asShortBuffer().put((short[]) arr, offset, length);
+ break;
+ case INT:
+ buffer.asIntBuffer().put((int[]) arr, offset, length);
+ break;
+ case LONG:
+ buffer.asLongBuffer().put((long[]) arr, offset, length);
+ break;
+ case FLOAT:
+ buffer.asFloatBuffer().put((float[]) arr, offset, length);
+ break;
+ case DOUBLE:
+ buffer.asDoubleBuffer().put((double[]) arr, offset, length);
+ break;
+ default:
+ throw new IllegalStateException("Unexpected value: " + eleType);
+ }
+ }
+ }
+ if (writeMode) {
+ writerIndex += numBytes;
+ }
+ }
+
+ public void writeArray(
+ Object arr, int offset, int length, Types.JavaArray eleType, boolean autoFill) {
+ coverMemoryWithArray(-1, arr, offset, length, eleType, autoFill);
+ }
+
/** Write a primitive array into buffer with size varint encoded into the buffer. */
- public void writePrimitiveArrayWithSize(Object arr, int offset, int numBytes) {
- int idx = writerIndex;
- ensure(idx + 5 + numBytes);
- idx += _unsafeWriteVarUint32(numBytes);
- Platform.copyMemory(arr, offset, heapMemory, address + idx, numBytes);
- writerIndex = idx + numBytes;
+ public void writeArrayWithSize(Object arr, int offset, int length, Types.JavaArray eleType) {
+ int numBytes = length * eleType.bytesPerEle;
+ ensure(writerIndex + 5 + numBytes);
+ writerIndex += _unsafeWriteVarUint32(numBytes);
+ writeArray(arr, offset, length, eleType, false);
}
- public void writePrimitiveArrayAlignedSize(Object arr, int offset, int numBytes) {
+ /*--------------------------------------------------------------------------------*/
+ public void writeArrayAlignedSize(Object arr, int offset, int length, Types.JavaArray eleType) {
+ int numBytes = length * eleType.bytesPerEle;
writeVarUint32Aligned(numBytes);
- final int writerIdx = writerIndex;
- final int newIdx = writerIdx + numBytes;
- ensure(newIdx);
- Platform.copyMemory(arr, offset, heapMemory, address + writerIdx, numBytes);
- writerIndex = newIdx;
+ ensure(writerIndex + numBytes);
+ writeArray(arr, offset, length, eleType, false);
}
- public void writePrimitiveArray(Object arr, int offset, int numBytes) {
- final int writerIdx = writerIndex;
- final int newIdx = writerIdx + numBytes;
- ensure(newIdx);
- Platform.copyMemory(arr, offset, heapMemory, address + writerIdx, numBytes);
- writerIndex = newIdx;
- }
+ /*--------------------------------------------------------------------------------*/
/** For off-heap buffer, this will make a heap buffer internally. */
public void grow(int neededSize) {
@@ -1250,7 +1390,7 @@ private void growBuffer(int length) {
? length << 2
: (int) Math.min(length * 1.5d, Integer.MAX_VALUE - 8);
byte[] data = new byte[newSize];
- copyToUnsafe(0, data, Platform.BYTE_ARRAY_OFFSET, size());
+ copyTo(0, data, 0, size, Types.JavaArray.BYTE, false);
initHeapBuffer(data, 0, data.length);
}
@@ -1298,7 +1438,7 @@ public void readerIndex(int readerIndex) {
// CHECKSTYLE.OFF:MethodName
public int _unsafeHeapReaderIndex() {
// CHECKSTYLE.ON:MethodName
- return readerIndex + heapOffset;
+ return readerIndex + memoryOffset;
}
// CHECKSTYLE.OFF:MethodName
@@ -2167,21 +2307,13 @@ private long skipPadding(long pos, int b) {
}
public byte[] readBytes(int length) {
- int readerIdx = readerIndex;
byte[] bytes = new byte[length];
// use subtract to avoid overflow
- if (length > size - readerIdx) {
+ if (length > size - readerIndex) {
streamReader.readTo(bytes, 0, length);
return bytes;
}
- byte[] heapMemory = this.heapMemory;
- if (heapMemory != null) {
- // System.arraycopy faster for some jdk than Unsafe.
- System.arraycopy(heapMemory, heapOffset + readerIdx, bytes, 0, length);
- } else {
- Platform.copyMemory(null, address + readerIdx, bytes, Platform.BYTE_ARRAY_OFFSET, length);
- }
- readerIndex = readerIdx + length;
+ readToUnchecked(bytes, 0, length, Types.JavaArray.BYTE);
return bytes;
}
@@ -2195,8 +2327,7 @@ public void readBytes(byte[] dst, int dstIndex, int length) {
if (dstIndex < 0 || dstIndex > dst.length - length) {
throwIndexOOBExceptionForRead();
}
- copyToUnsafe(readerIdx, dst, Platform.BYTE_ARRAY_OFFSET + dstIndex, length);
- readerIndex = readerIdx + length;
+ readToUnchecked(dst, dstIndex, length, Types.JavaArray.BYTE);
}
public void readBytes(byte[] dst) {
@@ -2226,7 +2357,7 @@ private long slowReadBytesAsInt64(int remaining, int len) {
long result = 0;
byte[] heapMemory = this.heapMemory;
if (heapMemory != null) {
- for (int i = 0, start = heapOffset + readerIdx; i < len; i++) {
+ for (int i = 0, start = memoryOffset + readerIdx; i < len; i++) {
result |= (((long) heapMemory[start + i]) & 0xff) << (i * 8);
}
} else {
@@ -2246,7 +2377,7 @@ public int read(ByteBuffer dst) {
return streamReader.readToByteBuffer(dst);
}
if (heapMemory != null) {
- dst.put(heapMemory, readerIndex + heapOffset, len);
+ dst.put(heapMemory, readerIndex + memoryOffset, len);
} else {
dst.put(sliceAsByteBuffer(readerIdx, len));
}
@@ -2261,7 +2392,7 @@ public void read(ByteBuffer dst, int len) {
streamReader.readToByteBuffer(dst, len);
} else {
if (heapMemory != null) {
- dst.put(heapMemory, readerIndex + heapOffset, len);
+ dst.put(heapMemory, readerIndex + memoryOffset, len);
} else {
dst.put(sliceAsByteBuffer(readerIdx, len));
}
@@ -2332,10 +2463,9 @@ public byte[] readBytesAndSize() {
}
byte[] heapMemory = this.heapMemory;
if (heapMemory != null) {
- System.arraycopy(heapMemory, heapOffset + readerIdx, arr, 0, numBytes);
+ System.arraycopy(heapMemory, memoryOffset + readerIdx, arr, 0, numBytes);
} else {
- Platform.UNSAFE.copyMemory(
- null, address + readerIdx, arr, Platform.BYTE_ARRAY_OFFSET, numBytes);
+ Platform.copyMemory(null, address + readerIdx, arr, Platform.BYTE_ARRAY_OFFSET, numBytes);
}
readerIndex = readerIdx + numBytes;
return arr;
@@ -2350,51 +2480,31 @@ public byte[] readBytesWithAlignedSize() {
streamReader.readTo(arr, 0, numBytes);
return arr;
}
- Platform.UNSAFE.copyMemory(
+ Platform.copyMemory(
this.heapMemory, this.address + readerIdx, arr, Platform.BYTE_ARRAY_OFFSET, numBytes);
readerIndex = readerIdx + numBytes;
return arr;
}
- /** This method should be used to read data written by {@link #writePrimitiveArrayWithSize}. */
+ /** This method should be used to read data written by {@link #writeArrayWithSize}. */
public char[] readChars(int numBytes) {
- int readerIdx = readerIndex;
- final char[] chars = new char[numBytes >> 1];
- // use subtract to avoid overflow
- if (readerIdx > size - numBytes) {
- streamReader.readToUnsafe(chars, 0, numBytes);
- return chars;
- }
- Platform.copyMemory(
- heapMemory, address + readerIdx, chars, Platform.CHAR_ARRAY_OFFSET, numBytes);
- readerIndex = readerIdx + numBytes;
+ int charLength = numBytes >> 1;
+ final char[] chars = new char[charLength];
+ readTo(chars, 0, charLength, Types.JavaArray.CHAR);
return chars;
}
- public void readChars(char[] chars, int offset, int numBytes) {
- final int readerIdx = readerIndex;
- // use subtract to avoid overflow
- if (readerIdx > size - numBytes) {
- streamReader.readToUnsafe(chars, offset, numBytes);
- return;
- }
- Platform.copyMemory(heapMemory, address + readerIdx, chars, offset, numBytes);
- readerIndex = readerIdx + numBytes;
- }
-
@CodegenInvoke
public char[] readCharsAndSize() {
final int numBytes = readBinarySize();
- int readerIdx = readerIndex;
- final char[] arr = new char[numBytes >> 1];
+ int length = numBytes >> 1;
+ assert numBytes % 2 == 0;
+ final char[] arr = new char[length];
// use subtract to avoid overflow
- if (readerIdx > size - numBytes) {
- streamReader.readToUnsafe(arr, 0, numBytes);
- return arr;
+ if (readerIndex > size - numBytes) {
+ streamReader.fillBuffer(numBytes - (size - readerIndex));
}
- Platform.UNSAFE.copyMemory(
- heapMemory, address + readerIdx, arr, Platform.CHAR_ARRAY_OFFSET, numBytes);
- readerIndex = readerIdx + numBytes;
+ readToUnchecked(arr, 0, length, Types.JavaArray.CHAR);
return arr;
}
@@ -2404,35 +2514,151 @@ public char[] readCharsWithAlignedSize() {
}
public long[] readLongs(int numBytes) {
- int readerIdx = readerIndex;
int numElements = numBytes >> 3;
+ assert (numBytes & 7) == 0;
final long[] longs = new long[numElements];
// use subtract to avoid overflow
- if (readerIdx > size - numBytes) {
- streamReader.readToUnsafe(longs, 0, numElements);
- return longs;
+ if (readerIndex > size - numBytes) {
+ streamReader.fillBuffer(numBytes - (size - readerIndex));
}
- Platform.copyMemory(
- heapMemory, address + readerIdx, longs, Platform.LONG_ARRAY_OFFSET, numBytes);
- readerIndex = readerIdx + numBytes;
+ readToUnchecked(longs, 0, numElements, Types.JavaArray.LONG);
return longs;
}
- /**
- * Bulk copy method. Copies {@code numBytes} bytes to target unsafe object and pointer. NOTE: This
- * is a unsafe method, no check here, please be carefully.
- */
- public void readToUnsafe(Object target, long targetPointer, int numBytes) {
- int remaining = size - readerIndex;
- if (numBytes > remaining) {
- streamReader.readToUnsafe(target, targetPointer, numBytes);
+ /*--------------------------------------------------------------------------------*/
+ // 此函数依赖调用者事先调整好buffer的position, 并且他不会改变readerIndex
+ private void copyToBoolsInner(boolean[] target, int offset, int length) {
+ // Fast Path: Use pooling and chunking for large arrays.
+ if (length >= BOOLEAN_TRANSFER_THRESHOLD) {
+ byte[] tmpBytes = BufferPool.INSTANCE.borrow(length, true);
+ // If borrowing was successful, proceed with the optimized path.
+ if (tmpBytes != null && tmpBytes.length >= BOOLEAN_TRANSFER_THRESHOLD / 3) {
+ int remaining = length;
+ int currentOffset = offset;
+ while (remaining > 0) {
+ int chunkSize = Math.min(remaining, tmpBytes.length);
+ buffer.get(tmpBytes, 0, chunkSize);
+ for (int i = 0; i < chunkSize; i++) {
+ target[currentOffset + i] = (tmpBytes[i] == 1);
+ }
+ remaining -= chunkSize;
+ currentOffset += chunkSize;
+ }
+ BufferPool.INSTANCE.release(tmpBytes);
+ return;
+ }
+ }
+ // Fallback Path: For small arrays or if the buffer pool was exhausted.
+ int limit = offset + length;
+ for (int i = offset; i < limit; i++) {
+ target[i] = (buffer.get() != 0);
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ // bufOffset为负数代表为阅读模式,使用readerIndex, 否则为纯copy, 不会对指针有影响
+ public void copyTo(
+ int bufOffset,
+ Object target,
+ int offset,
+ int length,
+ Types.JavaArray eleType,
+ boolean checkSize) {
+ boolean readMode = bufOffset < 0;
+ if (readMode) {
+ bufOffset = readerIndex;
+ }
+ int numBytes = length * eleType.bytesPerEle;
+ if (checkSize) {
+ int remaining = size - bufOffset;
+ if (numBytes > remaining) {
+ streamReader.fillBuffer(numBytes - remaining);
+ }
+ }
+ if (eleType == Types.JavaArray.BYTE && onHeap) {
+ System.arraycopy(heapMemory, memoryOffset + bufOffset, target, offset, numBytes);
+ } else {
+ if (!Platform.IS_ANDROID) {
+ Platform.copyMemory(
+ heapMemory,
+ address + bufOffset,
+ target,
+ eleType.arrayMemOffset + (long) offset * eleType.bytesPerEle,
+ numBytes);
+ } else {
+ buffer.position(bufOffset);
+ switch (eleType) {
+ case BOOL:
+ copyToBoolsInner((boolean[]) target, offset, length);
+ break;
+ case BYTE:
+ buffer.get((byte[]) target, offset, length);
+ break;
+ case CHAR:
+ buffer.asCharBuffer().get((char[]) target, offset, length);
+ break;
+ case SHORT:
+ buffer.asShortBuffer().get((short[]) target, offset, length);
+ break;
+ case INT:
+ buffer.asIntBuffer().get((int[]) target, offset, length);
+ break;
+ case LONG:
+ buffer.asLongBuffer().get((long[]) target, offset, length);
+ break;
+ case FLOAT:
+ buffer.asFloatBuffer().get((float[]) target, offset, length);
+ break;
+ case DOUBLE:
+ buffer.asDoubleBuffer().get((double[]) target, offset, length);
+ break;
+ default:
+ throw new IllegalStateException("Unsupported element type: " + eleType);
+ }
+ }
+ }
+ if (readMode) {
+ readerIndex += numBytes;
+ }
+ }
+
+ public void copyTo(int offset, MemoryBuffer target, int targetOffset, int numBytes) {
+ final long thisPointer = this.address + offset;
+ final long otherPointer = target.address + targetOffset;
+ if ((numBytes | offset | targetOffset) >= 0
+ && thisPointer <= this.addressLimit - numBytes
+ && otherPointer <= target.addressLimit - numBytes) {
+ if (Platform.IS_ANDROID) {
+ int thisOldLimit = this.buffer.limit();
+ this.buffer.position(offset);
+ this.buffer.limit(offset + numBytes);
+ target.buffer.position(targetOffset);
+ target.buffer.put(this.buffer);
+ this.buffer.limit(thisOldLimit);
+ } else {
+ Platform.copyMemory(
+ this.heapMemory, thisPointer, target.heapMemory, otherPointer, numBytes);
+ }
} else {
- int readerIdx = readerIndex;
- Platform.copyMemory(heapMemory, address + readerIdx, target, targetPointer, numBytes);
- readerIndex = readerIdx + numBytes;
+ throw new IndexOutOfBoundsException(
+ String.format(
+ "offset=%d, targetOffset=%d, numBytes=%d, address=%d, targetAddress=%d",
+ offset, targetOffset, numBytes, this.address, target.address));
}
}
+ public void readTo(Object target, int offset, int length, Types.JavaArray eleType) {
+ copyTo(-1, target, offset, length, eleType, true);
+ }
+
+ public void readToUnchecked(Object target, int offset, int length, Types.JavaArray eleType) {
+ copyTo(-1, target, offset, length, eleType, false);
+ }
+
+ /*--------------------------------------------------------------------------------*/
+
+ /*--------------------------------------------------------------------------------*/
+
public void checkReadableBytes(int minimumReadableBytes) {
// use subtract to avoid overflow
int remaining = size - readerIndex;
@@ -2447,7 +2673,7 @@ public void checkReadableBytes(int minimumReadableBytes) {
*/
public byte[] getRemainingBytes() {
int length = size - readerIndex;
- if (heapMemory != null && size == length && heapOffset == 0) {
+ if (heapMemory != null && size == length && memoryOffset == 0) {
return heapMemory;
} else {
return getBytes(readerIndex, length);
@@ -2455,42 +2681,50 @@ public byte[] getRemainingBytes() {
}
// ------------------------- Read Methods Finished -------------------------------------
-
/**
* Bulk copy method. Copies {@code numBytes} bytes to target unsafe object and pointer. NOTE: This
* is a unsafe method, no check here, please be carefully.
*/
- public void copyToUnsafe(long offset, Object target, long targetPointer, int numBytes) {
+ @NotForAndroid
+ @SuppressWarnings("deprecation")
+ public void copyToDirectUnsafe(int offset, long targetAddress, int numBytes) {
final long thisPointer = this.address + offset;
checkArgument(thisPointer + numBytes <= addressLimit);
- Platform.copyMemory(this.heapMemory, thisPointer, target, targetPointer, numBytes);
+ if (Platform.IS_ANDROID) {
+ if (onHeap) {
+ Platform.throwException(
+ new OperationNotSupportedException(
+ "Cannot copy heap memory to native address on Android."));
+ } else {
+ // android的copyMemory只支持这个三个参数的(堆外内存拷贝)
+ Platform.UNSAFE.copyMemory(thisPointer, targetAddress, numBytes);
+ }
+ return;
+ }
+ Platform.copyMemory(this.heapMemory, thisPointer, null, targetAddress, numBytes);
}
/**
* Bulk copy method. Copies {@code numBytes} bytes from source unsafe object and pointer. NOTE:
* This is an unsafe method, no check here, please be careful.
*/
- public void copyFromUnsafe(long offset, Object source, long sourcePointer, long numBytes) {
+ @NotForAndroid
+ @SuppressWarnings("deprecation")
+ public void copyFromDirectUnsafe(long offset, long sourcePointer, long numBytes) {
final long thisPointer = this.address + offset;
checkArgument(thisPointer + numBytes <= addressLimit);
- Platform.copyMemory(source, sourcePointer, this.heapMemory, thisPointer, numBytes);
- }
-
- public void copyTo(int offset, MemoryBuffer target, int targetOffset, int numBytes) {
- final byte[] thisHeapRef = this.heapMemory;
- final byte[] otherHeapRef = target.heapMemory;
- final long thisPointer = this.address + offset;
- final long otherPointer = target.address + targetOffset;
- if ((numBytes | offset | targetOffset) >= 0
- && thisPointer <= this.addressLimit - numBytes
- && otherPointer <= target.addressLimit - numBytes) {
- UNSAFE.copyMemory(thisHeapRef, thisPointer, otherHeapRef, otherPointer, numBytes);
- } else {
- throw new IndexOutOfBoundsException(
- String.format(
- "offset=%d, targetOffset=%d, numBytes=%d, address=%d, targetAddress=%d",
- offset, targetOffset, numBytes, this.address, target.address));
+ if (Platform.IS_ANDROID) {
+ if (onHeap) {
+ Platform.throwException(
+ new OperationNotSupportedException(
+ "Cannot copy heap memory to native address on Android."));
+ } else {
+ // android的copyMemory只支持这个三个参数的(堆外内存拷贝)
+ Platform.UNSAFE.copyMemory(sourcePointer, thisPointer, numBytes);
+ }
+ return;
}
+ Platform.copyMemory(null, sourcePointer, this.heapMemory, thisPointer, numBytes);
}
public void copyFrom(int offset, MemoryBuffer source, int sourcePointer, int numBytes) {
@@ -2498,7 +2732,7 @@ public void copyFrom(int offset, MemoryBuffer source, int sourcePointer, int num
}
public byte[] getBytes(int index, int length) {
- if (index == 0 && heapMemory != null && heapOffset == 0) {
+ if (index == 0 && heapMemory != null && memoryOffset == 0) {
// Arrays.copyOf is an intrinsics, which is faster
return Arrays.copyOf(heapMemory, length);
}
@@ -2506,20 +2740,10 @@ public byte[] getBytes(int index, int length) {
throwIndexOOBExceptionForRead(length);
}
byte[] data = new byte[length];
- copyToUnsafe(index, data, Platform.BYTE_ARRAY_OFFSET, length);
+ copyTo(index, data, 0, length, Types.JavaArray.BYTE, false);
return data;
}
- public void getBytes(int index, byte[] dst, int dstIndex, int length) {
- if (dstIndex > dst.length - length) {
- throwOOBException();
- }
- if (index > size - length) {
- throwOOBException();
- }
- copyToUnsafe(index, dst, Platform.BYTE_ARRAY_OFFSET + dstIndex, length);
- }
-
public MemoryBuffer slice(int offset) {
return slice(offset, size - offset);
}
@@ -2528,10 +2752,16 @@ public MemoryBuffer slice(int offset, int length) {
if (offset + length > size) {
throwOOBExceptionForRange(offset, length);
}
- if (heapMemory != null) {
- return new MemoryBuffer(heapMemory, heapOffset + offset, length);
+ if (onHeap) {
+ return new MemoryBuffer(heapMemory, memoryOffset + offset, length);
} else {
- return new MemoryBuffer(address + offset, length, offHeapBuffer);
+ if (this.buffer == null) {
+ // for android, can't construct a ByteBuffer from native address directly
+ return MemoryBuffer.fromNativeAddress(address + offset, length);
+ } else {
+ buffer.position(offset);
+ return MemoryBuffer.fromByteBuffer(buffer, length);
+ }
}
}
@@ -2539,21 +2769,19 @@ public ByteBuffer sliceAsByteBuffer() {
return sliceAsByteBuffer(readerIndex, size - readerIndex);
}
+ @PartialAndroidSupport
public ByteBuffer sliceAsByteBuffer(int offset, int length) {
if (offset + length > size) {
throwOOBExceptionForRange(offset, length);
}
if (heapMemory != null) {
- return ByteBuffer.wrap(heapMemory, heapOffset + offset, length).slice();
+ return ByteBuffer.wrap(heapMemory, memoryOffset + offset, length).slice();
} else {
- ByteBuffer offHeapBuffer = this.offHeapBuffer;
- if (offHeapBuffer != null) {
- ByteBuffer duplicate = offHeapBuffer.duplicate();
- int start = (int) (address - ByteBufferUtil.getAddress(duplicate));
- ByteBufferUtil.position(duplicate, start + offset);
- duplicate.limit(start + offset + length);
- return duplicate.slice();
+ if (this.buffer != null) {
+ this.buffer.position(offset);
+ return buffer.slice();
} else {
+ // for android, can't construct a ByteBuffer from native address directly
return ByteBufferUtil.createDirectByteBufferFromNativeAddress(address + offset, length);
}
}
@@ -2564,10 +2792,6 @@ private void throwOOBExceptionForRange(int offset, int length) {
String.format("offset(%d) + length(%d) exceeds size(%d): %s", offset, length, size, this));
}
- public ForyStreamReader getStreamReader() {
- return streamReader;
- }
-
/**
* Equals two memory buffer regions.
*
@@ -2597,9 +2821,9 @@ public String toString() {
+ ", heapMemory="
+ (heapMemory == null ? null : "len(" + heapMemory.length + ")")
+ ", heapOffset="
- + heapOffset
+ + memoryOffset
+ ", offHeapBuffer="
- + offHeapBuffer
+ + buffer
+ ", address="
+ address
+ ", addressLimit="
@@ -2612,57 +2836,71 @@ public void pointTo(byte[] buffer, int offset, int length) {
initHeapBuffer(buffer, offset, length);
}
- /** Creates a new memory buffer that targets to the given heap memory region. */
- public static MemoryBuffer fromByteArray(byte[] buffer, int offset, int length) {
- return new MemoryBuffer(buffer, offset, length, null);
+ /**
+ * Creates a new memory buffer that represents the provided native memory. The buffer will change
+ * into a heap buffer automatically if not enough.
+ */
+ // TODO: support android
+ @NotForAndroid(reason = "Android does not support support off-heap memory only by address")
+ public static MemoryBuffer fromNativeAddress(long address, int size) {
+ if (Platform.IS_ANDROID) {
+ throw new UnsupportedOperationException(
+ "Android does not support support off-heap memory only by address");
+ }
+ return new MemoryBuffer(address, null, size, null, false);
}
- public static MemoryBuffer fromByteArray(
- byte[] buffer, int offset, int length, ForyStreamReader streamReader) {
- return new MemoryBuffer(buffer, offset, length, streamReader);
- }
+ /*-------------------------------static named constructor----------------------------------*/
/** Creates a new memory buffer that targets to the given heap memory region. */
- public static MemoryBuffer fromByteArray(byte[] buffer) {
+ public static MemoryBuffer wrap(byte[] buffer) {
return new MemoryBuffer(buffer, 0, buffer.length);
}
/**
- * Creates a new memory buffer that represents the memory backing the given byte buffer section of
- * {@code [buffer.position(), buffer.limit())}. The buffer will change into a heap buffer
- * automatically if not enough.
+ * Creates a new memory segment that represents the memory backing the given byte buffer section
+ * of [buffer.position(), buffer,limit()].
*
- * @param buffer a direct buffer or heap buffer
+ * @param byteBuffer a direct buffer or heap buffer
*/
- public static MemoryBuffer fromByteBuffer(ByteBuffer buffer) {
- if (buffer.isDirect()) {
- return new MemoryBuffer(
- ByteBufferUtil.getAddress(buffer) + buffer.position(), buffer.remaining(), buffer);
- } else {
- int offset = buffer.arrayOffset() + buffer.position();
- return new MemoryBuffer(buffer.array(), offset, buffer.remaining());
- }
+ public static MemoryBuffer wrap(ByteBuffer byteBuffer) {
+ return fromByteBuffer(byteBuffer, byteBuffer.remaining());
}
- public static MemoryBuffer fromDirectByteBuffer(
- ByteBuffer buffer, int size, ForyStreamReader streamReader) {
- long offHeapAddress = ByteBufferUtil.getAddress(buffer) + buffer.position();
- return new MemoryBuffer(offHeapAddress, size, buffer, streamReader);
+ public static MemoryBuffer buffer(int size) {
+ return newHeapBuffer(size);
}
/**
- * Creates a new memory buffer that represents the provided native memory. The buffer will change
- * into a heap buffer automatically if not enough.
+ * Create a heap buffer of specified initial size. The buffer will grow automatically if not
+ * enough.
*/
- public static MemoryBuffer fromNativeAddress(long address, int size) {
- return new MemoryBuffer(address, size, null);
+ public static MemoryBuffer newHeapBuffer(int initialSize) {
+ return wrap(new byte[initialSize]);
+ }
+
+ public static MemoryBuffer bufferDirect(int size) {
+ return new MemoryBuffer(-1, ByteBuffer.allocateDirect(size), size, null, true);
}
/**
- * Create a heap buffer of specified initial size. The buffer will grow automatically if not
- * enough.
+ * Creates a new memory buffer that represents the native memory at the absolute address given by
+ * the pointer.
+ *
+ * @param length The size of this memory buffer.
+ * @param byteBuffer The byte buffer whose memory is represented by this memory buffer which
*/
- public static MemoryBuffer newHeapBuffer(int initialSize) {
- return fromByteArray(new byte[initialSize]);
+ private static MemoryBuffer fromByteBuffer(ByteBuffer byteBuffer, int length) {
+ if (byteBuffer.isDirect()) {
+ return new MemoryBuffer(-1, byteBuffer, length, null, false);
+ } else {
+ int offset = byteBuffer.arrayOffset() + byteBuffer.position();
+ return new MemoryBuffer(byteBuffer.array(), offset, byteBuffer.remaining());
+ }
+ }
+
+ public static MemoryBuffer fromDirectByteBuffer(
+ ByteBuffer buffer, int size, ForyStreamReader streamReader) {
+ return new MemoryBuffer(-1, buffer, size, streamReader, false);
}
}
diff --git a/java/fory-core/src/main/java/org/apache/fory/memory/MemoryUtils.java b/java/fory-core/src/main/java/org/apache/fory/memory/MemoryUtils.java
index 1eee8d6915..bc81d1c43f 100644
--- a/java/fory-core/src/main/java/org/apache/fory/memory/MemoryUtils.java
+++ b/java/fory-core/src/main/java/org/apache/fory/memory/MemoryUtils.java
@@ -21,51 +21,11 @@
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
-import java.nio.ByteBuffer;
import org.apache.fory.util.Preconditions;
/** Memory utils for fory. */
public class MemoryUtils {
- public static MemoryBuffer buffer(int size) {
- return wrap(new byte[size]);
- }
-
- public static MemoryBuffer buffer(long address, int size) {
- return MemoryBuffer.fromNativeAddress(address, size);
- }
-
- /**
- * Creates a new memory segment that targets to the given heap memory region.
- *
- *
This method should be used to turn short lived byte arrays into memory segments.
- *
- * @param buffer The heap memory region.
- * @return A new memory segment that targets the given heap memory region.
- */
- public static MemoryBuffer wrap(byte[] buffer, int offset, int length) {
- return MemoryBuffer.fromByteArray(buffer, offset, length);
- }
-
- public static MemoryBuffer wrap(byte[] buffer) {
- return MemoryBuffer.fromByteArray(buffer);
- }
-
- /**
- * Creates a new memory segment that represents the memory backing the given byte buffer section
- * of [buffer.position(), buffer,limit()).
- *
- * @param buffer a direct buffer or heap buffer
- */
- public static MemoryBuffer wrap(ByteBuffer buffer) {
- if (buffer.isDirect()) {
- return MemoryBuffer.fromByteBuffer(buffer);
- } else {
- int offset = buffer.arrayOffset() + buffer.position();
- return MemoryBuffer.fromByteArray(buffer.array(), offset, buffer.remaining());
- }
- }
-
// Lazy load offset and also follow graalvm offset auto replace pattern.
private static class Offset {
private static final long BAS_BUF_BUF;
@@ -105,7 +65,7 @@ public static void wrap(ByteArrayOutputStream stream, MemoryBuffer buffer) {
}
/**
- * Wrap a @link MemoryBuffer} into a {@link ByteArrayOutputStream}. The count of stream will be
+ * Wrap a @{link MemoryBuffer} into a {@link ByteArrayOutputStream}. The count of stream will be
* the writerIndex of buffer.
*/
public static void wrap(MemoryBuffer buffer, ByteArrayOutputStream stream) {
diff --git a/java/fory-core/src/main/java/org/apache/fory/memory/Platform.java b/java/fory-core/src/main/java/org/apache/fory/memory/Platform.java
index 7d87262754..73926fe78a 100644
--- a/java/fory-core/src/main/java/org/apache/fory/memory/Platform.java
+++ b/java/fory-core/src/main/java/org/apache/fory/memory/Platform.java
@@ -33,8 +33,10 @@ public final class Platform {
@SuppressWarnings("restriction")
public static final Unsafe UNSAFE = _JDKAccess.UNSAFE;
+ public static final boolean IS_ANDROID = _JDKAccess.IS_ANDROID;
public static final int JAVA_VERSION = _JDKAccess.JAVA_VERSION;
- public static final boolean IS_LITTLE_ENDIAN = ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN;
+ public static final ByteOrder NATIVE_BYTE_ORDER = ByteOrder.nativeOrder();
+ public static final boolean IS_LITTLE_ENDIAN = NATIVE_BYTE_ORDER == ByteOrder.LITTLE_ENDIAN;
public static final Class> HEAP_BYTE_BUFFER_CLASS = ByteBuffer.allocate(1).getClass();
public static final Class> DIRECT_BYTE_BUFFER_CLASS = ByteBuffer.allocateDirect(1).getClass();
public static final int BOOLEAN_ARRAY_OFFSET;
@@ -220,6 +222,7 @@ public static void setMemory(long address, byte value, long size) {
UNSAFE.setMemory(address, size, value);
}
+ @Deprecated
public static void copyMemory(
Object src, long srcOffset, Object dst, long dstOffset, long length) {
if (length < UNSAFE_COPY_THRESHOLD) {
@@ -282,8 +285,15 @@ public static boolean arrayEquals(
return true;
}
+ private static void sneakyThrow(Throwable throwable) throws T {
+ throw (T) throwable; // 将受检异常强制转换为一个未知的泛型异常类型并抛出
+ }
+
/** Raises an exception bypassing compiler checks for checked exceptions. */
public static void throwException(Throwable t) {
+ if (IS_ANDROID) {
+ sneakyThrow(t);
+ }
UNSAFE.throwException(t);
}
diff --git a/java/fory-core/src/main/java/org/apache/fory/meta/ClassDefDecoder.java b/java/fory-core/src/main/java/org/apache/fory/meta/ClassDefDecoder.java
index 5a6ec59333..d531952466 100644
--- a/java/fory-core/src/main/java/org/apache/fory/meta/ClassDefDecoder.java
+++ b/java/fory-core/src/main/java/org/apache/fory/meta/ClassDefDecoder.java
@@ -66,7 +66,7 @@ static Tuple2 decodeClassDefBuf(
public static ClassDef decodeClassDef(ClassResolver resolver, MemoryBuffer buffer, long id) {
Tuple2 decoded = decodeClassDefBuf(buffer, resolver, id);
- MemoryBuffer classDefBuf = MemoryBuffer.fromByteArray(decoded.f0);
+ MemoryBuffer classDefBuf = MemoryBuffer.wrap(decoded.f0);
int numClasses = classDefBuf.readByte();
if (numClasses == NUM_CLASS_THRESHOLD) {
numClasses += classDefBuf.readVarUint32Small7();
diff --git a/java/fory-core/src/main/java/org/apache/fory/meta/ClassDefEncoder.java b/java/fory-core/src/main/java/org/apache/fory/meta/ClassDefEncoder.java
index 53c6b04675..7bdd139bcf 100644
--- a/java/fory-core/src/main/java/org/apache/fory/meta/ClassDefEncoder.java
+++ b/java/fory-core/src/main/java/org/apache/fory/meta/ClassDefEncoder.java
@@ -37,7 +37,6 @@
import org.apache.fory.Fory;
import org.apache.fory.collection.Tuple2;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.MemoryUtils;
import org.apache.fory.meta.ClassDef.FieldInfo;
import org.apache.fory.meta.ClassDef.FieldType;
import org.apache.fory.reflect.ReflectionUtils;
@@ -176,7 +175,7 @@ static MemoryBuffer encodeClassDef(
boolean isCompressed = false;
if (compressed.length < classDefBuf.writerIndex()) {
isCompressed = true;
- classDefBuf = MemoryBuffer.fromByteArray(compressed);
+ classDefBuf = MemoryBuffer.wrap(compressed);
classDefBuf.writerIndex(compressed.length);
}
return prependHeader(classDefBuf, isCompressed, hasFieldsMeta);
@@ -196,7 +195,7 @@ static MemoryBuffer prependHeader(
header |= HAS_FIELDS_META_FLAG;
}
header |= Math.min(metaSize, META_SIZE_MASKS);
- MemoryBuffer result = MemoryUtils.buffer(metaSize + 8);
+ MemoryBuffer result = MemoryBuffer.buffer(metaSize + 8);
result.writeInt64(header);
if (metaSize > META_SIZE_MASKS) {
result.writeVarUint32(metaSize - META_SIZE_MASKS);
diff --git a/java/fory-core/src/main/java/org/apache/fory/meta/TypeDefDecoder.java b/java/fory-core/src/main/java/org/apache/fory/meta/TypeDefDecoder.java
index 88cbceb714..adfc2ccd6e 100644
--- a/java/fory-core/src/main/java/org/apache/fory/meta/TypeDefDecoder.java
+++ b/java/fory-core/src/main/java/org/apache/fory/meta/TypeDefDecoder.java
@@ -46,7 +46,7 @@
class TypeDefDecoder {
public static ClassDef decodeClassDef(XtypeResolver resolver, MemoryBuffer inputBuffer, long id) {
Tuple2 decoded = decodeClassDefBuf(inputBuffer, resolver, id);
- MemoryBuffer buffer = MemoryBuffer.fromByteArray(decoded.f0);
+ MemoryBuffer buffer = MemoryBuffer.wrap(decoded.f0);
byte header = buffer.readByte();
int numFields = header & SMALL_NUM_FIELDS_THRESHOLD;
if (numFields == SMALL_NUM_FIELDS_THRESHOLD) {
diff --git a/java/fory-core/src/main/java/org/apache/fory/meta/TypeDefEncoder.java b/java/fory-core/src/main/java/org/apache/fory/meta/TypeDefEncoder.java
index 7981aba18b..873c5ad1a6 100644
--- a/java/fory-core/src/main/java/org/apache/fory/meta/TypeDefEncoder.java
+++ b/java/fory-core/src/main/java/org/apache/fory/meta/TypeDefEncoder.java
@@ -123,7 +123,7 @@ static MemoryBuffer encodeClassDef(
boolean isCompressed = false;
if (compressed.length < buffer.writerIndex()) {
isCompressed = true;
- buffer = MemoryBuffer.fromByteArray(compressed);
+ buffer = MemoryBuffer.wrap(compressed);
buffer.writerIndex(compressed.length);
}
return prependHeader(buffer, isCompressed, true);
diff --git a/java/fory-core/src/main/java/org/apache/fory/pool/ThreadPoolFory.java b/java/fory-core/src/main/java/org/apache/fory/pool/ThreadPoolFory.java
index 6f81066c93..95560679d5 100644
--- a/java/fory-core/src/main/java/org/apache/fory/pool/ThreadPoolFory.java
+++ b/java/fory-core/src/main/java/org/apache/fory/pool/ThreadPoolFory.java
@@ -28,12 +28,12 @@
import org.apache.fory.AbstractThreadSafeFory;
import org.apache.fory.Fory;
import org.apache.fory.annotation.Internal;
+import org.apache.fory.annotation.NotForAndroid;
import org.apache.fory.io.ForyInputStream;
import org.apache.fory.io.ForyReadableChannel;
import org.apache.fory.logging.Logger;
import org.apache.fory.logging.LoggerFactory;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.MemoryUtils;
import org.apache.fory.resolver.ClassChecker;
import org.apache.fory.serializer.BufferCallback;
import org.apache.fory.util.LoaderBinding;
@@ -100,6 +100,7 @@ public byte[] serialize(Object obj, BufferCallback callback) {
return execute(fory -> fory.serialize(obj, callback));
}
+ @NotForAndroid(reason = "Android does not support support off-heap memory only by address")
@Override
public MemoryBuffer serialize(Object obj, long address, int size) {
return execute(fory -> fory.serialize(obj, address, size));
@@ -148,6 +149,7 @@ public Object deserialize(byte[] bytes, Iterable outOfBandBuffers)
return execute(fory -> fory.deserialize(bytes, outOfBandBuffers));
}
+ @NotForAndroid(reason = "Android does not support support off-heap memory only by address")
@Override
public Object deserialize(long address, int size) {
return execute(fory -> fory.deserialize(address, size));
@@ -160,7 +162,7 @@ public Object deserialize(MemoryBuffer buffer) {
@Override
public Object deserialize(ByteBuffer byteBuffer) {
- return execute(fory -> fory.deserialize(MemoryUtils.wrap(byteBuffer)));
+ return execute(fory -> fory.deserialize(MemoryBuffer.wrap(byteBuffer)));
}
@Override
diff --git a/java/fory-core/src/main/java/org/apache/fory/resolver/ClassResolver.java b/java/fory-core/src/main/java/org/apache/fory/resolver/ClassResolver.java
index 0e62c54d40..1c02f24035 100644
--- a/java/fory-core/src/main/java/org/apache/fory/resolver/ClassResolver.java
+++ b/java/fory-core/src/main/java/org/apache/fory/resolver/ClassResolver.java
@@ -345,9 +345,11 @@ private void addDefaultSerializers() {
CollectionSerializers.registerDefaultSerializers(fory);
MapSerializers.registerDefaultSerializers(fory);
addDefaultSerializer(Locale.class, new LocaleSerializer(fory));
- addDefaultSerializer(
- LambdaSerializer.ReplaceStub.class,
- new LambdaSerializer(fory, LambdaSerializer.ReplaceStub.class));
+ if (!Platform.IS_ANDROID) {
+ addDefaultSerializer(
+ LambdaSerializer.ReplaceStub.class,
+ new LambdaSerializer(fory, LambdaSerializer.ReplaceStub.class));
+ }
addDefaultSerializer(
JdkProxySerializer.ReplaceStub.class,
new JdkProxySerializer(fory, JdkProxySerializer.ReplaceStub.class));
@@ -358,7 +360,7 @@ private void addDefaultSerializers() {
UnmodifiableSerializers.registerSerializers(fory);
ImmutableCollectionSerializers.registerSerializers(fory);
SubListSerializers.registerSerializers(fory, true);
- if (fory.getConfig().registerGuavaTypes()) {
+ if (fory.getConfig().registerGuavaTypes() && !Platform.IS_ANDROID) {
GuavaCollectionSerializers.registerDefaultSerializers(fory);
}
if (fory.getConfig().deserializeNonexistentClass()) {
diff --git a/java/fory-core/src/main/java/org/apache/fory/serializer/ArraySerializers.java b/java/fory-core/src/main/java/org/apache/fory/serializer/ArraySerializers.java
index dbb63f6c43..7ba32f8b6c 100644
--- a/java/fory-core/src/main/java/org/apache/fory/serializer/ArraySerializers.java
+++ b/java/fory-core/src/main/java/org/apache/fory/serializer/ArraySerializers.java
@@ -21,11 +21,9 @@
import java.lang.reflect.Array;
import java.util.Arrays;
-import java.util.IdentityHashMap;
import org.apache.fory.Fory;
import org.apache.fory.config.CompatibleMode;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.Platform;
import org.apache.fory.resolver.ClassInfo;
import org.apache.fory.resolver.ClassInfoHolder;
import org.apache.fory.resolver.ClassResolver;
@@ -34,7 +32,7 @@
import org.apache.fory.serializer.collection.ForyArrayAsListSerializer;
import org.apache.fory.type.GenericType;
import org.apache.fory.type.TypeUtils;
-import org.apache.fory.type.Types;
+import org.apache.fory.type.Types.JavaArray;
import org.apache.fory.util.Preconditions;
/** Serializers for array types. */
@@ -212,14 +210,14 @@ private Object[] newArray(int numElements) {
public static final class PrimitiveArrayBufferObject implements BufferObject {
private final Object array;
- private final int offset;
private final int elemSize;
private final int length;
+ private final JavaArray eleType;
- public PrimitiveArrayBufferObject(Object array, int offset, int elemSize, int length) {
+ public PrimitiveArrayBufferObject(Object array, int length, JavaArray eleType) {
this.array = array;
- this.offset = offset;
- this.elemSize = elemSize;
+ this.eleType = eleType;
+ this.elemSize = eleType.bytesPerEle;
this.length = length;
}
@@ -230,12 +228,7 @@ public int totalBytes() {
@Override
public void writeTo(MemoryBuffer buffer) {
- int size = Math.multiplyExact(length, elemSize);
- int writerIndex = buffer.writerIndex();
- int end = writerIndex + size;
- buffer.ensure(end);
- buffer.copyFromUnsafe(writerIndex, array, offset, size);
- buffer.writerIndex(end);
+ buffer.writeArray(array, 0, length, eleType, true);
}
@Override
@@ -252,12 +245,14 @@ public abstract static class PrimitiveArraySerializer
extends Serializers.CrossLanguageCompatibleSerializer {
protected final int offset;
protected final int elemSize;
+ protected final JavaArray eleType;
- public PrimitiveArraySerializer(Fory fory, Class cls) {
+ public PrimitiveArraySerializer(Fory fory, Class cls, JavaArray eleType) {
super(fory, cls);
- Class> innerType = TypeUtils.getArrayComponentInfo(cls).f0;
- this.offset = primitiveInfo.get(innerType)[0];
- this.elemSize = primitiveInfo.get(innerType)[1];
+ this.eleType = eleType;
+ // Class> innerType = TypeUtils.getArrayComponentInfo(cls).f0;
+ this.offset = eleType.arrayMemOffset;
+ this.elemSize = eleType.bytesPerEle;
}
@Override
@@ -274,17 +269,18 @@ public T xread(MemoryBuffer buffer) {
public static final class BooleanArraySerializer extends PrimitiveArraySerializer {
public BooleanArraySerializer(Fory fory) {
- super(fory, boolean[].class);
+ super(fory, boolean[].class, JavaArray.BOOL);
}
@Override
public void write(MemoryBuffer buffer, boolean[] value) {
if (fory.getBufferCallback() == null) {
- int size = Math.multiplyExact(value.length, elemSize);
- buffer.writePrimitiveArrayWithSize(value, offset, size);
+ // int size = Math.multiplyExact(value.length, elemSize);
+ // buffer.writePrimitiveArrayWithSize(value, offset, size);
+ buffer.writeArrayWithSize(value, 0, value.length, eleType);
} else {
fory.writeBufferObject(
- buffer, new PrimitiveArrayBufferObject(value, offset, elemSize, value.length));
+ buffer, new PrimitiveArrayBufferObject(value, value.length, eleType));
}
}
@@ -300,13 +296,14 @@ public boolean[] read(MemoryBuffer buffer) {
int size = buf.remaining();
int numElements = size / elemSize;
boolean[] values = new boolean[numElements];
- buf.copyToUnsafe(0, values, offset, size);
+ // buf.copyToUnsafe(0, values, offset, size);
+ buf.copyTo(0, values, 0, numElements, eleType, false);
return values;
} else {
int size = buffer.readVarUint32Small7();
int numElements = size / elemSize;
boolean[] values = new boolean[numElements];
- buffer.readToUnsafe(values, offset, size);
+ buffer.readTo(values, 0, numElements, eleType);
return values;
}
}
@@ -315,17 +312,18 @@ public boolean[] read(MemoryBuffer buffer) {
public static final class ByteArraySerializer extends PrimitiveArraySerializer {
public ByteArraySerializer(Fory fory) {
- super(fory, byte[].class);
+ super(fory, byte[].class, JavaArray.BYTE);
}
@Override
public void write(MemoryBuffer buffer, byte[] value) {
if (fory.getBufferCallback() == null) {
- int size = Math.multiplyExact(value.length, 1);
- buffer.writePrimitiveArrayWithSize(value, offset, size);
+ // int size = Math.multiplyExact(value.length, 1);
+ // buffer.writePrimitiveArrayWithSize(value, offset, size);
+ buffer.writeArrayWithSize(value, 0, value.length, eleType);
} else {
fory.writeBufferObject(
- buffer, new PrimitiveArrayBufferObject(value, offset, 1, value.length));
+ buffer, new PrimitiveArrayBufferObject(value, value.length, eleType));
}
}
@@ -340,12 +338,13 @@ public byte[] read(MemoryBuffer buffer) {
MemoryBuffer buf = fory.readBufferObject(buffer);
int size = buf.remaining();
byte[] values = new byte[size];
- buf.copyToUnsafe(0, values, offset, size);
+ // buf.copyToUnsafe(0, values, offset, size);
+ buf.copyTo(0, values, 0, size, eleType, false);
return values;
} else {
int size = buffer.readVarUint32Small7();
byte[] values = new byte[size];
- buffer.readToUnsafe(values, offset, size);
+ buffer.readTo(values, 0, size, eleType);
return values;
}
}
@@ -354,17 +353,18 @@ public byte[] read(MemoryBuffer buffer) {
public static final class CharArraySerializer extends PrimitiveArraySerializer {
public CharArraySerializer(Fory fory) {
- super(fory, char[].class);
+ super(fory, char[].class, JavaArray.CHAR);
}
@Override
public void write(MemoryBuffer buffer, char[] value) {
if (fory.getBufferCallback() == null) {
- int size = Math.multiplyExact(value.length, elemSize);
- buffer.writePrimitiveArrayWithSize(value, offset, size);
+ // int size = Math.multiplyExact(value.length, elemSize);
+ // buffer.writePrimitiveArrayWithSize(value, offset, size);
+ buffer.writeArrayWithSize(value, 0, value.length, eleType);
} else {
fory.writeBufferObject(
- buffer, new PrimitiveArrayBufferObject(value, offset, elemSize, value.length));
+ buffer, new PrimitiveArrayBufferObject(value, value.length, eleType));
}
}
@@ -380,13 +380,14 @@ public char[] read(MemoryBuffer buffer) {
int size = buf.remaining();
int numElements = size / elemSize;
char[] values = new char[numElements];
- buf.copyToUnsafe(0, values, offset, size);
+ // buf.copyToUnsafe(0, values, offset, size);
+ buf.copyTo(0, values, 0, numElements, eleType, false);
return values;
} else {
int size = buffer.readVarUint32Small7();
int numElements = size / elemSize;
char[] values = new char[numElements];
- buffer.readToUnsafe(values, offset, size);
+ buffer.readTo(values, 0, numElements, eleType);
return values;
}
}
@@ -405,17 +406,18 @@ public char[] xread(MemoryBuffer buffer) {
public static final class ShortArraySerializer extends PrimitiveArraySerializer {
public ShortArraySerializer(Fory fory) {
- super(fory, short[].class);
+ super(fory, short[].class, JavaArray.SHORT);
}
@Override
public void write(MemoryBuffer buffer, short[] value) {
if (fory.getBufferCallback() == null) {
- int size = Math.multiplyExact(value.length, elemSize);
- buffer.writePrimitiveArrayWithSize(value, offset, size);
+ // int size = Math.multiplyExact(value.length, elemSize);
+ // buffer.writePrimitiveArrayWithSize(value, offset, size);
+ buffer.writeArrayWithSize(value, 0, value.length, eleType);
} else {
fory.writeBufferObject(
- buffer, new PrimitiveArrayBufferObject(value, offset, elemSize, value.length));
+ buffer, new PrimitiveArrayBufferObject(value, value.length, eleType));
}
}
@@ -431,13 +433,14 @@ public short[] read(MemoryBuffer buffer) {
int size = buf.remaining();
int numElements = size / elemSize;
short[] values = new short[numElements];
- buf.copyToUnsafe(0, values, offset, size);
+ // buf.copyToUnsafe(0, values, offset, size);
+ buf.copyTo(0, values, 0, numElements, eleType, false);
return values;
} else {
int size = buffer.readVarUint32Small7();
int numElements = size / elemSize;
short[] values = new short[numElements];
- buffer.readToUnsafe(values, offset, size);
+ buffer.readTo(values, 0, numElements, eleType);
return values;
}
}
@@ -446,17 +449,18 @@ public short[] read(MemoryBuffer buffer) {
public static final class IntArraySerializer extends PrimitiveArraySerializer {
public IntArraySerializer(Fory fory) {
- super(fory, int[].class);
+ super(fory, int[].class, JavaArray.INT);
}
@Override
public void write(MemoryBuffer buffer, int[] value) {
if (fory.getBufferCallback() == null) {
- int size = Math.multiplyExact(value.length, elemSize);
- buffer.writePrimitiveArrayWithSize(value, offset, size);
+ // int size = Math.multiplyExact(value.length, elemSize);
+ // buffer.writePrimitiveArrayWithSize(value, offset, size);
+ buffer.writeArrayWithSize(value, 0, value.length, eleType);
} else {
fory.writeBufferObject(
- buffer, new PrimitiveArrayBufferObject(value, offset, elemSize, value.length));
+ buffer, new PrimitiveArrayBufferObject(value, value.length, eleType));
}
}
@@ -472,13 +476,14 @@ public int[] read(MemoryBuffer buffer) {
int size = buf.remaining();
int numElements = size / elemSize;
int[] values = new int[numElements];
- buf.copyToUnsafe(0, values, offset, size);
+ // buf.copyToUnsafe(0, values, offset, size);
+ buf.copyTo(0, values, 0, numElements, eleType, false);
return values;
} else {
int size = buffer.readVarUint32Small7();
int numElements = size / elemSize;
int[] values = new int[numElements];
- buffer.readToUnsafe(values, offset, size);
+ buffer.readTo(values, 0, numElements, eleType);
return values;
}
}
@@ -487,17 +492,18 @@ public int[] read(MemoryBuffer buffer) {
public static final class LongArraySerializer extends PrimitiveArraySerializer {
public LongArraySerializer(Fory fory) {
- super(fory, long[].class);
+ super(fory, long[].class, JavaArray.LONG);
}
@Override
public void write(MemoryBuffer buffer, long[] value) {
if (fory.getBufferCallback() == null) {
- int size = Math.multiplyExact(value.length, elemSize);
- buffer.writePrimitiveArrayWithSize(value, offset, size);
+ // int size = Math.multiplyExact(value.length, elemSize);
+ // buffer.writePrimitiveArrayWithSize(value, offset, size);
+ buffer.writeArrayWithSize(value, 0, value.length, eleType);
} else {
fory.writeBufferObject(
- buffer, new PrimitiveArrayBufferObject(value, offset, elemSize, value.length));
+ buffer, new PrimitiveArrayBufferObject(value, value.length, eleType));
}
}
@@ -513,13 +519,14 @@ public long[] read(MemoryBuffer buffer) {
int size = buf.remaining();
int numElements = size / elemSize;
long[] values = new long[numElements];
- buf.copyToUnsafe(0, values, offset, size);
+ // buf.copyToUnsafe(0, values, offset, size);
+ buf.copyTo(0, values, 0, numElements, eleType, false);
return values;
} else {
int size = buffer.readVarUint32Small7();
int numElements = size / elemSize;
long[] values = new long[numElements];
- buffer.readToUnsafe(values, offset, size);
+ buffer.readTo(values, 0, numElements, eleType);
return values;
}
}
@@ -528,17 +535,18 @@ public long[] read(MemoryBuffer buffer) {
public static final class FloatArraySerializer extends PrimitiveArraySerializer {
public FloatArraySerializer(Fory fory) {
- super(fory, float[].class);
+ super(fory, float[].class, JavaArray.FLOAT);
}
@Override
public void write(MemoryBuffer buffer, float[] value) {
if (fory.getBufferCallback() == null) {
- int size = Math.multiplyExact(value.length, elemSize);
- buffer.writePrimitiveArrayWithSize(value, offset, size);
+ // int size = Math.multiplyExact(value.length, elemSize);
+ // buffer.writePrimitiveArrayWithSize(value, offset, size);
+ buffer.writeArrayWithSize(value, 0, value.length, eleType);
} else {
fory.writeBufferObject(
- buffer, new PrimitiveArrayBufferObject(value, offset, elemSize, value.length));
+ buffer, new PrimitiveArrayBufferObject(value, value.length, eleType));
}
}
@@ -554,13 +562,14 @@ public float[] read(MemoryBuffer buffer) {
int size = buf.remaining();
int numElements = size / elemSize;
float[] values = new float[numElements];
- buf.copyToUnsafe(0, values, offset, size);
+ // buf.copyToUnsafe(0, values, offset, size);
+ buf.copyTo(0, values, 0, numElements, eleType, false);
return values;
} else {
int size = buffer.readVarUint32Small7();
int numElements = size / elemSize;
float[] values = new float[numElements];
- buffer.readToUnsafe(values, offset, size);
+ buffer.readTo(values, 0, numElements, eleType);
return values;
}
}
@@ -569,17 +578,18 @@ public float[] read(MemoryBuffer buffer) {
public static final class DoubleArraySerializer extends PrimitiveArraySerializer {
public DoubleArraySerializer(Fory fory) {
- super(fory, double[].class);
+ super(fory, double[].class, JavaArray.DOUBLE);
}
@Override
public void write(MemoryBuffer buffer, double[] value) {
if (fory.getBufferCallback() == null) {
- int size = Math.multiplyExact(value.length, elemSize);
- buffer.writePrimitiveArrayWithSize(value, offset, size);
+ // int size = Math.multiplyExact(value.length, elemSize);
+ // buffer.writePrimitiveArrayWithSize(value, offset, size);
+ buffer.writeArrayWithSize(value, 0, value.length, eleType);
} else {
fory.writeBufferObject(
- buffer, new PrimitiveArrayBufferObject(value, offset, elemSize, value.length));
+ buffer, new PrimitiveArrayBufferObject(value, value.length, eleType));
}
}
@@ -595,13 +605,14 @@ public double[] read(MemoryBuffer buffer) {
int size = buf.remaining();
int numElements = size / elemSize;
double[] values = new double[numElements];
- buf.copyToUnsafe(0, values, offset, size);
+ // buf.copyToUnsafe(0, values, offset, size);
+ buf.copyTo(0, values, 0, numElements, eleType, false);
return values;
} else {
int size = buffer.readVarUint32Small7();
int numElements = size / elemSize;
double[] values = new double[numElements];
- buffer.readToUnsafe(values, offset, size);
+ buffer.readTo(values, 0, numElements, eleType);
return values;
}
}
@@ -735,38 +746,6 @@ public static void registerDefaultSerializers(Fory fory) {
}
// ########################## utils ##########################
-
- static void writePrimitiveArray(
- MemoryBuffer buffer, Object arr, int offset, int numElements, int elemSize) {
- int size = Math.multiplyExact(numElements, elemSize);
- buffer.writeVarUint32Small7(size);
- int writerIndex = buffer.writerIndex();
- int end = writerIndex + size;
- buffer.ensure(end);
- buffer.copyFromUnsafe(writerIndex, arr, offset, size);
- buffer.writerIndex(end);
- }
-
- public static PrimitiveArrayBufferObject byteArrayBufferObject(byte[] array) {
- return new PrimitiveArrayBufferObject(array, Platform.BYTE_ARRAY_OFFSET, 1, array.length);
- }
-
- static final IdentityHashMap, int[]> primitiveInfo = new IdentityHashMap<>();
-
- static {
- primitiveInfo.put(
- boolean.class, new int[] {Platform.BOOLEAN_ARRAY_OFFSET, 1, Types.BOOL_ARRAY});
- primitiveInfo.put(byte.class, new int[] {Platform.BYTE_ARRAY_OFFSET, 1, Types.BINARY});
- primitiveInfo.put(
- char.class, new int[] {Platform.CHAR_ARRAY_OFFSET, 2, Fory.NOT_SUPPORT_XLANG});
- primitiveInfo.put(short.class, new int[] {Platform.SHORT_ARRAY_OFFSET, 2, Types.INT16_ARRAY});
- primitiveInfo.put(int.class, new int[] {Platform.INT_ARRAY_OFFSET, 4, Types.INT32_ARRAY});
- primitiveInfo.put(long.class, new int[] {Platform.LONG_ARRAY_OFFSET, 8, Types.INT64_ARRAY});
- primitiveInfo.put(float.class, new int[] {Platform.FLOAT_ARRAY_OFFSET, 4, Types.FLOAT32_ARRAY});
- primitiveInfo.put(
- double.class, new int[] {Platform.DOUBLE_ARRAY_OFFSET, 8, Types.FLOAT64_ARRAY});
- }
-
public abstract static class AbstractedNonexistentArrayClassSerializer extends Serializer {
protected final String className;
private final int dims;
diff --git a/java/fory-core/src/main/java/org/apache/fory/serializer/ForwardSerializer.java b/java/fory-core/src/main/java/org/apache/fory/serializer/ForwardSerializer.java
index 2df75a6f03..930da46305 100644
--- a/java/fory-core/src/main/java/org/apache/fory/serializer/ForwardSerializer.java
+++ b/java/fory-core/src/main/java/org/apache/fory/serializer/ForwardSerializer.java
@@ -28,7 +28,6 @@
import org.apache.fory.Fory;
import org.apache.fory.config.Language;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.MemoryUtils;
import org.apache.fory.memory.Platform;
import org.apache.fory.util.LoaderBinding;
import org.apache.fory.util.LoaderBinding.StagingType;
@@ -89,7 +88,7 @@ protected Object deserialize(T serializer, long address, int size) {
}
protected Object deserialize(T serializer, ByteBuffer byteBuffer) {
- return deserialize(serializer, MemoryUtils.wrap(byteBuffer));
+ return deserialize(serializer, MemoryBuffer.wrap(byteBuffer));
}
protected Object deserialize(T serializer, MemoryBuffer buffer) {
@@ -105,7 +104,7 @@ protected Object copy(T serializer, Object obj) {
public static class DefaultForyProxy extends SerializerProxy {
private final ThreadLocal bufferLocal =
- ThreadLocal.withInitial(() -> MemoryUtils.buffer(32));
+ ThreadLocal.withInitial(() -> MemoryBuffer.buffer(32));
/** Override this method to register custom serializers. */
@Override
diff --git a/java/fory-core/src/main/java/org/apache/fory/serializer/Serializers.java b/java/fory-core/src/main/java/org/apache/fory/serializer/Serializers.java
index ce936d7405..f5f6ce0dad 100644
--- a/java/fory-core/src/main/java/org/apache/fory/serializer/Serializers.java
+++ b/java/fory-core/src/main/java/org/apache/fory/serializer/Serializers.java
@@ -202,25 +202,32 @@ public T xread(MemoryBuffer buffer) {
}
}
- private static final ToIntFunction GET_CODER;
- private static final Function GET_VALUE;
-
- static {
- GET_VALUE = (Function) makeGetterFunction(StringBuilder.class.getSuperclass(), "getValue");
- ToIntFunction getCoder;
- try {
- Method getCoderMethod = StringBuilder.class.getSuperclass().getDeclaredMethod("getCoder");
- getCoder = (ToIntFunction) makeGetterFunction(getCoderMethod, int.class);
- } catch (NoSuchMethodException e) {
- getCoder = null;
- }
- GET_CODER = getCoder;
- }
-
public abstract static class AbstractStringBuilderSerializer
extends Serializer {
protected final StringSerializer stringSerializer;
+ private static final ToIntFunction GET_CODER;
+ private static final Function GET_VALUE;
+
+ private static final boolean RESTRICTED_STRING_BUILDER = Platform.IS_ANDROID;
+
+ static {
+ if (RESTRICTED_STRING_BUILDER) {
+ GET_CODER = null;
+ GET_VALUE = null;
+ } else {
+ GET_VALUE = (Function) makeGetterFunction(StringBuilder.class.getSuperclass(), "getValue");
+ ToIntFunction getCoder;
+ try {
+ Method getCoderMethod = StringBuilder.class.getSuperclass().getDeclaredMethod("getCoder");
+ getCoder = (ToIntFunction) makeGetterFunction(getCoderMethod, int.class);
+ } catch (NoSuchMethodException e) {
+ getCoder = null;
+ }
+ GET_CODER = getCoder;
+ }
+ }
+
public AbstractStringBuilderSerializer(Fory fory, Class type) {
super(fory, type);
stringSerializer = new StringSerializer(fory);
@@ -233,6 +240,12 @@ public void xwrite(MemoryBuffer buffer, T value) {
@Override
public void write(MemoryBuffer buffer, T value) {
+ if (RESTRICTED_STRING_BUILDER) {
+ // Restricted StringBuilder doesn't have getCoder method, so we use
+ // the StringSerializer to write the string.
+ stringSerializer.writeString(buffer, value.toString());
+ return;
+ }
if (GET_CODER != null) {
int coder = GET_CODER.applyAsInt(value);
byte[] v = (byte[]) GET_VALUE.apply(value);
diff --git a/java/fory-core/src/main/java/org/apache/fory/serializer/StringSerializer.java b/java/fory-core/src/main/java/org/apache/fory/serializer/StringSerializer.java
index f755f270b1..04692fe2d0 100644
--- a/java/fory-core/src/main/java/org/apache/fory/serializer/StringSerializer.java
+++ b/java/fory-core/src/main/java/org/apache/fory/serializer/StringSerializer.java
@@ -29,12 +29,14 @@
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.lang.reflect.Field;
+import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.function.BiFunction;
import java.util.function.Function;
import org.apache.fory.Fory;
import org.apache.fory.annotation.CodegenInvoke;
+import org.apache.fory.annotation.NotForAndroid;
import org.apache.fory.codegen.Expression;
import org.apache.fory.codegen.Expression.Invoke;
import org.apache.fory.codegen.Expression.StaticInvoke;
@@ -42,6 +44,7 @@
import org.apache.fory.memory.MemoryBuffer;
import org.apache.fory.memory.Platform;
import org.apache.fory.reflect.ReflectionUtils;
+import org.apache.fory.type.Types;
import org.apache.fory.util.MathUtils;
import org.apache.fory.util.Preconditions;
import org.apache.fory.util.StringEncodingUtils;
@@ -66,44 +69,56 @@ public final class StringSerializer extends ImmutableSerializer {
private static final Byte UTF16_BOXED = UTF16;
private static final byte UTF8 = 2;
private static final int DEFAULT_BUFFER_SIZE = 1024;
+ private static final boolean RESTRICTED_STRING = Platform.IS_ANDROID;
// Make offset compatible with graalvm native image.
private static final long STRING_VALUE_FIELD_OFFSET;
private static class Offset {
// Make offset compatible with graalvm native image.
- private static final long STRING_CODER_FIELD_OFFSET;
+ private static final long
+ STRING_CODER_FIELD_OFFSET; // android can't access this field through reflection
static {
- try {
- STRING_CODER_FIELD_OFFSET =
- Platform.objectFieldOffset(String.class.getDeclaredField("coder"));
- } catch (NoSuchFieldException e) {
- throw new RuntimeException(e);
+ if (RESTRICTED_STRING) {
+ STRING_CODER_FIELD_OFFSET = -1;
+ } else {
+ try {
+ STRING_CODER_FIELD_OFFSET =
+ Platform.objectFieldOffset(String.class.getDeclaredField("coder"));
+ } catch (NoSuchFieldException e) {
+ throw new RuntimeException(e);
+ }
}
}
}
static {
- Field valueField = ReflectionUtils.getFieldNullable(String.class, "value");
- // Java8 string
- STRING_VALUE_FIELD_IS_CHARS = valueField != null && valueField.getType() == char[].class;
- // Java11 string
- STRING_VALUE_FIELD_IS_BYTES = valueField != null && valueField.getType() == byte[].class;
- try {
- // Make offset compatible with graalvm native image.
- STRING_VALUE_FIELD_OFFSET =
- Platform.objectFieldOffset(String.class.getDeclaredField("value"));
- } catch (NoSuchFieldException e) {
- throw new RuntimeException(e);
+ if (Platform.IS_ANDROID) {
+ STRING_VALUE_FIELD_IS_CHARS = false;
+ STRING_VALUE_FIELD_IS_BYTES = true;
+ STRING_VALUE_FIELD_OFFSET = -1;
+ } else {
+ Field valueField = ReflectionUtils.getFieldNullable(String.class, "value");
+ // Java8 string
+ STRING_VALUE_FIELD_IS_CHARS = valueField != null && valueField.getType() == char[].class;
+ // Java11 string
+ STRING_VALUE_FIELD_IS_BYTES = valueField != null && valueField.getType() == byte[].class;
+ try {
+ // Make offset compatible with graalvm native image.
+ STRING_VALUE_FIELD_OFFSET =
+ Platform.objectFieldOffset(String.class.getDeclaredField("value"));
+ } catch (NoSuchFieldException e) {
+ throw new RuntimeException(e);
+ }
+ // String length field for android.
+ Preconditions.checkArgument(
+ ReflectionUtils.getFieldNullable(String.class, "count") == null,
+ "Current jdk not supported");
+ Preconditions.checkArgument(
+ ReflectionUtils.getFieldNullable(String.class, "offset") == null,
+ "Current jdk not supported");
}
- // String length field for android.
- Preconditions.checkArgument(
- ReflectionUtils.getFieldNullable(String.class, "count") == null,
- "Current jdk not supported");
- Preconditions.checkArgument(
- ReflectionUtils.getFieldNullable(String.class, "offset") == null,
- "Current jdk not supported");
}
private final boolean compressString;
@@ -223,8 +238,10 @@ public String readCompressedBytesString(MemoryBuffer buffer) {
if (coder == UTF8) {
byte[] data;
if (writeNumUtf16BytesForUtf8Encoding) {
+ System.out.println("Read compressed bytes string with UTF8 encoding, optimized for perf");
data = readBytesUTF8PerfOptimized(buffer, numBytes);
} else {
+ System.out.println("Read compressed bytes string with UTF8 encoding");
data = readBytesUTF8(buffer, numBytes);
}
return newBytesStringZeroCopy(UTF16, data);
@@ -257,6 +274,26 @@ public String readCompressedCharsString(MemoryBuffer buffer) {
// Invoked by fory JIT
public void writeJavaString(MemoryBuffer buffer, String value) {
+ // TODO: haven't implemented a fast path in android version yet.
+ if (RESTRICTED_STRING) {
+ byte coder;
+ byte[] bytes;
+ if (StringUtils.isLatin1(value)) {
+ // 如果是 Latin-1 字符串,我们就用 ISO_8859_1 编码来获取单字节数组。
+ // 这与 String 内部的 LATIN1 存储方式兼容。
+ coder = LATIN1; // 0 for LATIN1
+ bytes = value.getBytes(StandardCharsets.ISO_8859_1);
+ } else {
+ // 如果包含更复杂的字符,我们就用 UTF-16LE 编码。
+ // 这与 String 内部的 UTF16 存储方式兼容。
+ // 注意:Java 内部是 UTF-16,通常是 Little Endian。如果您的接收端有特定要求,请调整。
+ coder = UTF16; // 1 for UTF16
+ bytes = value.getBytes(StandardCharsets.UTF_16LE);
+ }
+ // 调用您原来的核心序列化方法,这个方法不需要任何改动。
+ writeBytesString(buffer, coder, bytes);
+ return;
+ }
if (STRING_VALUE_FIELD_IS_BYTES) {
if (compressString) {
writeCompressedBytesString(buffer, value);
@@ -293,14 +330,29 @@ public String readJavaString(MemoryBuffer buffer) {
@CodegenInvoke
public void writeCompressedBytesString(MemoryBuffer buffer, String value) {
- final byte[] bytes = (byte[]) Platform.getObject(value, STRING_VALUE_FIELD_OFFSET);
- final byte coder = Platform.getByte(value, Offset.STRING_CODER_FIELD_OFFSET);
+ final byte[] bytes;
+ final byte coder;
+ if (RESTRICTED_STRING) {
+ if (StringUtils.isLatin1(value)) {
+ coder = LATIN1; // 0 for LATIN1
+ bytes = value.getBytes(StandardCharsets.ISO_8859_1);
+ } else {
+ coder = UTF16; // 1 for UTF16
+ bytes = value.getBytes(StandardCharsets.UTF_16LE);
+ }
+ } else {
+ bytes = (byte[]) Platform.getObject(value, STRING_VALUE_FIELD_OFFSET);
+ coder = Platform.getByte(value, Offset.STRING_CODER_FIELD_OFFSET);
+ }
if (coder == LATIN1 || bestCoder(bytes) == UTF16) {
+ System.out.println("Write compressed bytes string with LATIN1 or UTF16 encoding");
writeBytesString(buffer, coder, bytes);
} else {
if (writeNumUtf16BytesForUtf8Encoding) {
+ System.out.println("Write compressed bytes string with UTF8 encoding, optimized for perf");
writeBytesUTF8PerfOptimized(buffer, bytes);
} else {
+ System.out.println("Write compressed bytes string with UTF8 encoding");
writeBytesUTF8(buffer, bytes);
}
}
@@ -308,6 +360,7 @@ public void writeCompressedBytesString(MemoryBuffer buffer, String value) {
@CodegenInvoke
public void writeCompressedCharsString(MemoryBuffer buffer, String value) {
+ assert !RESTRICTED_STRING; // Android version not implemented yet. 我们限制了Android只用byte
final char[] chars = (char[]) Platform.getObject(value, STRING_VALUE_FIELD_OFFSET);
final byte coder = bestCoder(chars);
if (coder == LATIN1) {
@@ -325,8 +378,20 @@ public void writeCompressedCharsString(MemoryBuffer buffer, String value) {
@CodegenInvoke
public static void writeBytesString(MemoryBuffer buffer, String value) {
- byte[] bytes = (byte[]) Platform.getObject(value, STRING_VALUE_FIELD_OFFSET);
- byte coder = Platform.getByte(value, Offset.STRING_CODER_FIELD_OFFSET);
+ final byte[] bytes;
+ final byte coder;
+ if (RESTRICTED_STRING) {
+ if (StringUtils.isLatin1(value)) {
+ coder = LATIN1; // 0 for LATIN1
+ bytes = value.getBytes(StandardCharsets.ISO_8859_1);
+ } else {
+ coder = UTF16; // 1 for UTF16
+ bytes = value.getBytes(StandardCharsets.UTF_16LE);
+ }
+ } else {
+ bytes = (byte[]) Platform.getObject(value, STRING_VALUE_FIELD_OFFSET);
+ coder = Platform.getByte(value, Offset.STRING_CODER_FIELD_OFFSET);
+ }
writeBytesString(buffer, coder, bytes);
}
@@ -337,27 +402,14 @@ public static void writeBytesString(MemoryBuffer buffer, byte coder, byte[] byte
// The `ensure` ensure next operations are safe without bound checks,
// and inner heap buffer doesn't change.
buffer.ensure(writerIndex + 9 + bytesLen); // 1 byte coder + varint max 8 bytes
- final byte[] targetArray = buffer.getHeapMemory();
- if (targetArray != null) {
- // Some JDK11 Unsafe.copyMemory will `copyMemoryChecks`, and
- // jvm doesn't eliminate well in some jdk.
- final int targetIndex = buffer._unsafeHeapWriterIndex();
- int arrIndex = targetIndex;
- arrIndex += LittleEndian.putVarUint36Small(targetArray, arrIndex, header);
- writerIndex += arrIndex - targetIndex;
- System.arraycopy(bytes, 0, targetArray, arrIndex, bytesLen);
- } else {
- writerIndex += buffer._unsafePutVarUint36Small(writerIndex, header);
- long offHeapAddress = buffer.getUnsafeAddress();
- Platform.copyMemory(
- bytes, Platform.BYTE_ARRAY_OFFSET, null, offHeapAddress + writerIndex, bytesLen);
- }
- writerIndex += bytesLen;
- buffer._unsafeWriterIndex(writerIndex);
+ int consumedLen = buffer._unsafePutVarUint36Small(writerIndex, header);
+ buffer._increaseWriterIndexUnsafe(consumedLen);
+ buffer.writeArray(bytes, 0, bytesLen, Types.JavaArray.BYTE, false);
}
@CodegenInvoke
public void writeCharsString(MemoryBuffer buffer, String value) {
+ assert !RESTRICTED_STRING; // Android version not implemented yet. 我们限制了Android只用byte
final char[] chars = (char[]) Platform.getObject(value, STRING_VALUE_FIELD_OFFSET);
if (StringUtils.isLatin(chars)) {
writeCharsLatin1(buffer, chars, chars.length);
@@ -440,10 +492,12 @@ public byte[] readBytesUnCompressedUTF16(MemoryBuffer buffer, int numBytes) {
}
public char[] readCharsUTF16(MemoryBuffer buffer, int numBytes) {
- char[] chars = new char[numBytes >> 1];
+ int elementNum = numBytes >> 1;
+ assert (numBytes & 1) == 0;
+ char[] chars = new char[elementNum];
if (Platform.IS_LITTLE_ENDIAN) {
// FIXME JDK11 utf16 string uses little-endian order.
- buffer.readChars(chars, Platform.CHAR_ARRAY_OFFSET, numBytes);
+ buffer.readTo(chars, 0, elementNum, Types.JavaArray.CHAR);
} else {
buffer.checkReadableBytes(numBytes);
final byte[] targetArray = buffer.getHeapMemory();
@@ -512,15 +566,16 @@ public String readCharsUTF8PerfOptimized(MemoryBuffer buffer, int numBytes) {
}
public void writeCharsLatin1(MemoryBuffer buffer, char[] chars, int numBytes) {
+ assert !RESTRICTED_STRING; // Android version not implemented yet. 我们限制了Android只用byte
int writerIndex = buffer.writerIndex();
long header = ((long) numBytes << 2) | LATIN1;
buffer.ensure(writerIndex + 5 + numBytes);
byte[] targetArray = buffer.getHeapMemory();
if (targetArray != null) {
- final int targetIndex = buffer._unsafeHeapWriterIndex();
- int arrIndex = targetIndex;
- arrIndex += LittleEndian.putVarUint36Small(targetArray, arrIndex, header);
- writerIndex += arrIndex - targetIndex;
+ int arrIndex = buffer._unsafeHeapWriterIndex();
+ int varLen = LittleEndian.putVarUint36Small(targetArray, arrIndex, header);
+ arrIndex += varLen;
+ writerIndex += varLen;
for (int i = 0; i < numBytes; i++) {
targetArray[arrIndex + i] = (byte) chars[i];
}
@@ -537,27 +592,25 @@ public void writeCharsLatin1(MemoryBuffer buffer, char[] chars, int numBytes) {
}
public void writeCharsUTF16(MemoryBuffer buffer, char[] chars, int numChars) {
+ assert !RESTRICTED_STRING; // Android version not implemented yet. 我们限制了Android只用byte
int numBytes = MathUtils.doubleExact(numChars);
int writerIndex = buffer.writerIndex();
long header = ((long) numBytes << 2) | UTF16;
buffer.ensure(writerIndex + 5 + numBytes);
final byte[] targetArray = buffer.getHeapMemory();
if (targetArray != null) {
- final int targetIndex = buffer._unsafeHeapWriterIndex();
- int arrIndex = targetIndex;
- arrIndex += LittleEndian.putVarUint36Small(targetArray, arrIndex, header);
- writerIndex += arrIndex - targetIndex + numBytes;
+ int targetIndex = buffer._unsafeHeapWriterIndex();
+ int varIntLen = LittleEndian.putVarUint36Small(targetArray, targetIndex, header);
+ writerIndex += varIntLen;
+ targetIndex += varIntLen;
if (Platform.IS_LITTLE_ENDIAN) {
// FIXME JDK11 utf16 string uses little-endian order.
- Platform.UNSAFE.copyMemory(
- chars,
- Platform.CHAR_ARRAY_OFFSET,
- targetArray,
- Platform.BYTE_ARRAY_OFFSET + arrIndex,
- numBytes);
+ buffer.coverMemoryWithArray(
+ writerIndex, chars, 0, numBytes / 2, Types.JavaArray.CHAR, false);
} else {
- heapWriteCharsUTF16BE(chars, arrIndex, numBytes, targetArray);
+ heapWriteCharsUTF16BE(chars, targetIndex, numBytes, targetArray);
}
+ writerIndex += numBytes;
} else {
writerIndex += buffer._unsafePutVarUint36Small(writerIndex, header);
writerIndex = offHeapWriteCharsUTF16(buffer, chars, writerIndex, numBytes);
@@ -566,6 +619,7 @@ public void writeCharsUTF16(MemoryBuffer buffer, char[] chars, int numChars) {
}
public void writeCharsUTF8(MemoryBuffer buffer, char[] chars) {
+ assert !RESTRICTED_STRING; // Android version not implemented yet. 我们限制了Android只用byte
int estimateMaxBytes = chars.length * 3;
// num bytes of utf8 should be smaller than utf16, otherwise we should
// utf16 instead.
@@ -608,6 +662,7 @@ public void writeCharsUTF8(MemoryBuffer buffer, char[] chars) {
}
public void writeCharsUTF8PerfOptimized(MemoryBuffer buffer, char[] chars) {
+ assert !RESTRICTED_STRING; // Android version not implemented yet. 我们限制了Android只用byte
int estimateMaxBytes = chars.length * 3;
int numBytes = MathUtils.doubleExact(chars.length);
// noinspection Duplicates
@@ -730,6 +785,21 @@ public static String newCharsStringZeroCopy(char[] data) {
// coder param first to make inline call args
// `(buffer.readByte(), buffer.readBytesWithSizeEmbedded())` work.
public static String newBytesStringZeroCopy(byte coder, byte[] data) {
+ if (RESTRICTED_STRING) {
+ Charset charset;
+ if (coder == LATIN1) { // LATIN1
+ charset = StandardCharsets.ISO_8859_1;
+ } else if (coder == UTF16) { // UTF16
+ charset = StandardCharsets.UTF_16LE; // 注意:Java 内部是 UTF-16,通常是 Little Endian。
+ } else if (coder == UTF8) { // UTF8
+ charset = StandardCharsets.UTF_8;
+ } else {
+ throw new IllegalArgumentException("Unknown coder type: " + coder);
+ }
+ // 使用标准的、会产生拷贝的构造函数。
+ // 这是在 Android 上唯一保证有效的方法。
+ return new String(data, charset);
+ }
if (coder == LATIN1) {
// 700% faster than unsafe put field in java11, only 10% slower than `new String(str)` for
// string length 230.
@@ -753,7 +823,11 @@ public static String newBytesStringZeroCopy(byte coder, byte[] data) {
}
}
+ @NotForAndroid
private static BiFunction getCharsStringZeroCopyCtr() {
+ if (RESTRICTED_STRING) {
+ return null; // Android version not implemented yet.
+ }
if (!STRING_VALUE_FIELD_IS_CHARS) {
return null;
}
@@ -777,7 +851,11 @@ private static BiFunction getCharsStringZeroCopyCtr() {
}
}
+ @NotForAndroid
private static BiFunction getBytesStringZeroCopyCtr() {
+ if (RESTRICTED_STRING) {
+ return null; // Android version not implemented yet.
+ }
if (!STRING_VALUE_FIELD_IS_BYTES) {
return null;
}
@@ -803,7 +881,11 @@ private static BiFunction getBytesStringZeroCopyCtr() {
}
}
+ @NotForAndroid
private static Function getLatinBytesStringZeroCopyCtr() {
+ if (RESTRICTED_STRING) {
+ return null; // Android version not implemented yet.
+ }
if (!STRING_VALUE_FIELD_IS_BYTES) {
return null;
}
@@ -825,15 +907,18 @@ private static Function getLatinBytesStringZeroCopyCtr() {
}
private static MethodHandle getJavaStringZeroCopyCtrHandle() {
+ assert !RESTRICTED_STRING;
Preconditions.checkArgument(Platform.JAVA_VERSION >= 8);
if (STRING_LOOK_UP == null) {
return null;
}
try {
if (STRING_VALUE_FIELD_IS_CHARS) {
+ // android can't get this
return STRING_LOOK_UP.findConstructor(
String.class, MethodType.methodType(void.class, char[].class, boolean.class));
} else {
+ // android can't get this
return STRING_LOOK_UP.findConstructor(
String.class, MethodType.methodType(void.class, byte[].class, byte.class));
}
@@ -844,6 +929,7 @@ private static MethodHandle getJavaStringZeroCopyCtrHandle() {
private static void heapWriteCharsUTF16BE(
char[] chars, int arrIndex, int numBytes, byte[] targetArray) {
+ assert !RESTRICTED_STRING; // Android version not implemented yet. 我们限制了Android只用byte
// Write to heap memory then copy is 250% faster than unsafe write to direct memory.
int charIndex = 0;
for (int i = arrIndex, end = i + numBytes; i < end; i += 2) {
@@ -855,6 +941,7 @@ private static void heapWriteCharsUTF16BE(
private int offHeapWriteCharsUTF16(
MemoryBuffer buffer, char[] chars, int writerIndex, int numBytes) {
+ assert !RESTRICTED_STRING; // Android version not implemented yet. 我们限制了Android只用byte
byte[] tmpArray = getByteArray(numBytes);
int charIndex = 0;
for (int i = 0; i < numBytes; i += 2) {
diff --git a/java/fory-core/src/main/java/org/apache/fory/serializer/collection/CollectionSerializers.java b/java/fory-core/src/main/java/org/apache/fory/serializer/collection/CollectionSerializers.java
index c77d01b569..fa1c0120b4 100644
--- a/java/fory-core/src/main/java/org/apache/fory/serializer/collection/CollectionSerializers.java
+++ b/java/fory-core/src/main/java/org/apache/fory/serializer/collection/CollectionSerializers.java
@@ -57,6 +57,7 @@
import org.apache.fory.serializer.ReplaceResolveSerializer;
import org.apache.fory.serializer.Serializer;
import org.apache.fory.serializer.Serializers;
+import org.apache.fory.type.Types;
import org.apache.fory.util.Preconditions;
import org.apache.fory.util.unsafe._JDKAccess;
@@ -634,8 +635,7 @@ public BitSetSerializer(Fory fory, Class type) {
@Override
public void write(MemoryBuffer buffer, BitSet set) {
long[] values = set.toLongArray();
- buffer.writePrimitiveArrayWithSize(
- values, Platform.LONG_ARRAY_OFFSET, Math.multiplyExact(values.length, 8));
+ buffer.writeArrayWithSize(values, 0, values.length, Types.JavaArray.LONG);
}
@Override
@@ -820,7 +820,9 @@ public static void registerDefaultSerializers(Fory fory) {
CopyOnWriteArrayList.class,
new CopyOnWriteArrayListSerializer(fory, CopyOnWriteArrayList.class));
final Class setFromMapClass = Collections.newSetFromMap(new HashMap<>()).getClass();
- resolver.registerSerializer(setFromMapClass, new SetFromMapSerializer(fory, setFromMapClass));
+ if (!Platform.IS_ANDROID) {
+ resolver.registerSerializer(setFromMapClass, new SetFromMapSerializer(fory, setFromMapClass));
+ }
resolver.registerSerializer(
ConcurrentHashMap.KeySetView.class,
new ConcurrentHashMapKeySetViewSerializer(fory, ConcurrentHashMap.KeySetView.class));
diff --git a/java/fory-core/src/main/java/org/apache/fory/type/Types.java b/java/fory-core/src/main/java/org/apache/fory/type/Types.java
index 3a2a287d6d..110de4a1f9 100644
--- a/java/fory-core/src/main/java/org/apache/fory/type/Types.java
+++ b/java/fory-core/src/main/java/org/apache/fory/type/Types.java
@@ -22,6 +22,8 @@
import static org.apache.fory.collection.Collections.ofHashMap;
import java.util.Map;
+import org.apache.fory.Fory;
+import org.apache.fory.memory.Platform;
import org.apache.fory.util.Preconditions;
public class Types {
@@ -164,6 +166,27 @@ public class Types {
public static final int UNKNOWN = 63;
+ public enum JavaArray {
+ BOOL(Platform.BOOLEAN_ARRAY_OFFSET, 1, Types.BOOL_ARRAY),
+ BYTE(Platform.BYTE_ARRAY_OFFSET, 1, Types.BINARY),
+ CHAR(Platform.CHAR_ARRAY_OFFSET, 2, Fory.NOT_SUPPORT_XLANG),
+ SHORT(Platform.SHORT_ARRAY_OFFSET, 2, Types.INT16_ARRAY),
+ INT(Platform.INT_ARRAY_OFFSET, 4, Types.INT32_ARRAY),
+ LONG(Platform.LONG_ARRAY_OFFSET, 8, Types.INT64_ARRAY),
+ FLOAT(Platform.FLOAT_ARRAY_OFFSET, 4, Types.FLOAT32_ARRAY),
+ DOUBLE(Platform.DOUBLE_ARRAY_OFFSET, 8, Types.FLOAT64_ARRAY);
+
+ public final int arrayMemOffset;
+ public final int bytesPerEle;
+ public final int typeCode;
+
+ JavaArray(int arrayMemOffset, int bytesPerEle, int typeCode) {
+ this.arrayMemOffset = arrayMemOffset;
+ this.bytesPerEle = bytesPerEle;
+ this.typeCode = typeCode;
+ }
+ }
+
// Helper methods
public static boolean isStructType(int value) {
return value == STRUCT
diff --git a/java/fory-core/src/main/java/org/apache/fory/util/StringEncodingUtils.java b/java/fory-core/src/main/java/org/apache/fory/util/StringEncodingUtils.java
index 4d121aa2ee..2af9e86855 100644
--- a/java/fory-core/src/main/java/org/apache/fory/util/StringEncodingUtils.java
+++ b/java/fory-core/src/main/java/org/apache/fory/util/StringEncodingUtils.java
@@ -118,7 +118,7 @@ public static int convertUTF16ToUTF8(byte[] src, byte[] dst, int dp) {
/**
* A fast convert algorithm to convert an utf8 encoded byte array into an utf16 encoded byte
- * array.
+ * array.(aware: utf16le)
*/
public static int convertUTF8ToUTF16(byte[] src, int offset, int len, byte[] dst) {
final int end = offset + len;
diff --git a/java/fory-core/src/main/java/org/apache/fory/util/StringUtils.java b/java/fory-core/src/main/java/org/apache/fory/util/StringUtils.java
index 394f429b34..b7612af37f 100644
--- a/java/fory-core/src/main/java/org/apache/fory/util/StringUtils.java
+++ b/java/fory-core/src/main/java/org/apache/fory/util/StringUtils.java
@@ -303,4 +303,15 @@ public static boolean isLatin(char[] chars, int start) {
}
return isLatin;
}
+
+ // need to be optimized
+ public static boolean isLatin1(String s) {
+ for (int i = 0; i < s.length(); i++) {
+ // char 是16位的,Latin-1 字符的码点都在 255 (0xFF) 以内
+ if (s.charAt(i) > 0xFF) {
+ return false;
+ }
+ }
+ return true;
+ }
}
diff --git a/java/fory-core/src/main/java/org/apache/fory/util/unsafe/_JDKAccess.java b/java/fory-core/src/main/java/org/apache/fory/util/unsafe/_JDKAccess.java
index 1a5765fb3f..0911c47494 100644
--- a/java/fory-core/src/main/java/org/apache/fory/util/unsafe/_JDKAccess.java
+++ b/java/fory-core/src/main/java/org/apache/fory/util/unsafe/_JDKAccess.java
@@ -55,18 +55,25 @@ public class _JDKAccess {
// CHECKSTYLE.ON:TypeName
public static final int JAVA_VERSION;
public static final boolean IS_OPEN_J9;
+ public static final boolean IS_ANDROID;
public static final Unsafe UNSAFE;
public static final Class> _INNER_UNSAFE_CLASS;
public static final Object _INNER_UNSAFE;
static {
- String property = System.getProperty("java.specification.version");
- if (property.startsWith("1.")) {
- property = property.substring(2);
+ IS_ANDROID = checkIsAndroid();
+ if (IS_ANDROID) {
+ IS_OPEN_J9 = false;
+ JAVA_VERSION = 8; // TODO: 只是一个尝试,之后一定要改
+ } else {
+ String property = System.getProperty("java.specification.version");
+ if (property.startsWith("1.")) {
+ property = property.substring(2);
+ }
+ String jmvName = System.getProperty("java.vm.name", "");
+ IS_OPEN_J9 = jmvName.contains("OpenJ9");
+ JAVA_VERSION = Integer.parseInt(property);
}
- String jmvName = System.getProperty("java.vm.name", "");
- IS_OPEN_J9 = jmvName.contains("OpenJ9");
- JAVA_VERSION = Integer.parseInt(property);
Unsafe unsafe;
try {
Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
@@ -77,6 +84,8 @@ public class _JDKAccess {
}
UNSAFE = unsafe;
if (JAVA_VERSION >= 11) {
+ // TODO: make sure android can't reach here
+ assert !IS_ANDROID;
try {
Field theInternalUnsafeField = Unsafe.class.getDeclaredField("theInternalUnsafe");
theInternalUnsafeField.setAccessible(true);
@@ -91,6 +100,16 @@ public class _JDKAccess {
}
}
+ private static boolean checkIsAndroid() {
+ try {
+ // try to load a class that only android has
+ Class.forName("android.os.Build");
+ return true;
+ } catch (ClassNotFoundException e) {
+ return false;
+ }
+ }
+
private static final ClassValue lookupCache =
new ClassValue() {
@Override
diff --git a/java/fory-core/src/test/java/org/apache/fory/CrossLanguageTest.java b/java/fory-core/src/test/java/org/apache/fory/CrossLanguageTest.java
index 1d887425e5..6e18bf0946 100644
--- a/java/fory-core/src/test/java/org/apache/fory/CrossLanguageTest.java
+++ b/java/fory-core/src/test/java/org/apache/fory/CrossLanguageTest.java
@@ -60,7 +60,6 @@
import org.apache.fory.logging.Logger;
import org.apache.fory.logging.LoggerFactory;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.MemoryUtils;
import org.apache.fory.serializer.ArraySerializersTest;
import org.apache.fory.serializer.BufferObject;
import org.apache.fory.serializer.EnumSerializerTest;
@@ -114,7 +113,7 @@ public static A create() {
@Test
public void testBuffer() throws IOException {
- MemoryBuffer buffer = MemoryUtils.buffer(32);
+ MemoryBuffer buffer = MemoryBuffer.buffer(32);
buffer.writeBoolean(true);
buffer.writeByte(Byte.MAX_VALUE);
buffer.writeInt16(Short.MAX_VALUE);
@@ -136,7 +135,7 @@ public void testBuffer() throws IOException {
"test_buffer",
dataFile.toAbsolutePath().toString());
Assert.assertTrue(executeCommand(command, 30));
- buffer = MemoryUtils.wrap(Files.readAllBytes(dataFile));
+ buffer = MemoryBuffer.wrap(Files.readAllBytes(dataFile));
Assert.assertTrue(buffer.readBoolean());
Assert.assertEquals(buffer.readByte(), Byte.MAX_VALUE);
Assert.assertEquals(buffer.readInt16(), Short.MAX_VALUE);
@@ -150,7 +149,7 @@ public void testBuffer() throws IOException {
@Test
public void testMurmurHash3() throws IOException {
- MemoryBuffer buffer = MemoryUtils.buffer(32);
+ MemoryBuffer buffer = MemoryBuffer.buffer(32);
byte[] hash1 = Hashing.murmur3_128(47).hashBytes(new byte[] {1, 2, 8}).asBytes();
buffer.writeBytes(hash1);
byte[] hash2 =
@@ -229,7 +228,7 @@ public void testCrossLanguageSerializer() throws Exception {
.withRefTracking(true)
.requireClassRegistration(false)
.build();
- MemoryBuffer buffer = MemoryUtils.buffer(32);
+ MemoryBuffer buffer = MemoryBuffer.buffer(32);
fory.serialize(buffer, true);
fory.serialize(buffer, false);
fory.serialize(buffer, -1);
@@ -309,7 +308,7 @@ public void testCrossLanguageSerializer() throws Exception {
"test_cross_language_serializer",
dataFile.toAbsolutePath().toString());
Assert.assertTrue(executeCommand(command, 30));
- MemoryBuffer buffer2 = MemoryUtils.wrap(Files.readAllBytes(dataFile));
+ MemoryBuffer buffer2 = MemoryBuffer.wrap(Files.readAllBytes(dataFile));
function.accept(buffer2, true);
}
@@ -407,7 +406,7 @@ public void testCrossLanguageReference() throws Exception {
list.add(map);
map.put("k1", map);
map.put("k2", list);
- MemoryBuffer buffer = MemoryUtils.buffer(32);
+ MemoryBuffer buffer = MemoryBuffer.buffer(32);
fory.serialize(buffer, list);
Consumer function =
@@ -432,7 +431,7 @@ public void testCrossLanguageReference() throws Exception {
"test_cross_language_reference",
dataFile.toAbsolutePath().toString());
Assert.assertTrue(executeCommand(command, 30));
- MemoryBuffer buffer2 = MemoryUtils.wrap(Files.readAllBytes(dataFile));
+ MemoryBuffer buffer2 = MemoryBuffer.wrap(Files.readAllBytes(dataFile));
function.accept(buffer2);
}
@@ -670,8 +669,8 @@ public void testOutOfBandBuffer() throws Exception {
outOfBandDataFile.toAbsolutePath().toString());
Assert.assertTrue(executeCommand(command, 30));
- MemoryBuffer inBandBuffer = MemoryUtils.wrap(Files.readAllBytes(intBandDataFile));
- outOfBandBuffer = MemoryUtils.wrap(Files.readAllBytes(outOfBandDataFile));
+ MemoryBuffer inBandBuffer = MemoryBuffer.wrap(Files.readAllBytes(intBandDataFile));
+ outOfBandBuffer = MemoryBuffer.wrap(Files.readAllBytes(outOfBandDataFile));
int numBuffers = outOfBandBuffer.readInt32();
buffers = new ArrayList<>();
for (int i = 0; i < numBuffers; i++) {
diff --git a/java/fory-core/src/test/java/org/apache/fory/ForyTest.java b/java/fory-core/src/test/java/org/apache/fory/ForyTest.java
index 335cc9720e..081200b2dc 100644
--- a/java/fory-core/src/test/java/org/apache/fory/ForyTest.java
+++ b/java/fory-core/src/test/java/org/apache/fory/ForyTest.java
@@ -62,7 +62,6 @@
import org.apache.fory.exception.ForyException;
import org.apache.fory.exception.InsecureException;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.MemoryUtils;
import org.apache.fory.memory.Platform;
import org.apache.fory.resolver.MetaContext;
import org.apache.fory.serializer.ArraySerializersTest;
@@ -168,7 +167,7 @@ public void basicTest(boolean referenceTracking) {
public void testSerializationToBuffer(Language language) {
Fory fory1 = Fory.builder().withLanguage(language).requireClassRegistration(false).build();
Fory fory2 = Fory.builder().withLanguage(language).requireClassRegistration(false).build();
- MemoryBuffer buffer = MemoryUtils.buffer(64);
+ MemoryBuffer buffer = MemoryBuffer.buffer(64);
assertSerializationToBuffer(fory1, fory2, buffer);
}
@@ -176,7 +175,7 @@ public void testSerializationToBuffer(Language language) {
public void testSerializationSlicedBuffer(Language language) {
Fory fory1 = Fory.builder().withLanguage(language).requireClassRegistration(false).build();
Fory fory2 = Fory.builder().withLanguage(language).requireClassRegistration(false).build();
- MemoryBuffer buffer0 = MemoryUtils.buffer(64);
+ MemoryBuffer buffer0 = MemoryBuffer.buffer(64);
buffer0.writeInt64(-1);
buffer0.writeInt64(-1);
buffer0.readInt64();
@@ -520,7 +519,7 @@ public void testSerializeJavaObject() {
fory.deserializeJavaObjectAndClass(fory.serializeJavaObjectAndClass(beanA)), beanA);
assertEquals(
fory.deserializeJavaObjectAndClass(
- MemoryBuffer.fromByteArray(fory.serializeJavaObjectAndClass(beanA))),
+ MemoryBuffer.wrap(fory.serializeJavaObjectAndClass(beanA))),
beanA);
}
diff --git a/java/fory-core/src/test/java/org/apache/fory/StreamTest.java b/java/fory-core/src/test/java/org/apache/fory/StreamTest.java
index b57ad362f2..2aa5c6297a 100644
--- a/java/fory-core/src/test/java/org/apache/fory/StreamTest.java
+++ b/java/fory-core/src/test/java/org/apache/fory/StreamTest.java
@@ -84,7 +84,7 @@ public synchronized int read(byte[] b, int off, int len) {
return 1;
}
});
- MemoryBuffer buffer = MemoryBuffer.fromByteArray(bytes, 0, 0, stream);
+ MemoryBuffer buffer = new MemoryBuffer(bytes, 0, 0, stream);
for (int i = 0; i < 10; i++) {
assertEquals(buffer.readByte(), i);
assertEquals(buffer.readChar(), i);
@@ -164,7 +164,7 @@ public void testOutputStream() throws IOException {
bas.flush();
ByteArrayInputStream bis = new ByteArrayInputStream(bas.toByteArray());
ForyInputStream stream = of(bis);
- MemoryBuffer buf = MemoryBuffer.fromByteArray(bas.toByteArray());
+ MemoryBuffer buf = MemoryBuffer.wrap(bas.toByteArray());
Object newObj = fory.deserialize(stream);
assertEquals(newObj, beanA);
newObj = fory.deserialize(buf);
@@ -178,7 +178,7 @@ public void testOutputStream() throws IOException {
// test reader buffer grow
bis = new ByteArrayInputStream(bas.toByteArray());
stream = of(bis);
- buf = MemoryBuffer.fromByteArray(bas.toByteArray());
+ buf = MemoryBuffer.wrap(bas.toByteArray());
newObj = fory.deserialize(stream);
assertEquals(newObj, beanA);
newObj = fory.deserialize(buf);
@@ -215,7 +215,7 @@ public synchronized int read(byte[] b, int off, int len) throws IOException {
// test reader buffer grow
bis = new ByteArrayInputStream(bas.toByteArray());
stream = of(bis);
- MemoryBuffer buf = MemoryBuffer.fromByteArray(bas.toByteArray());
+ MemoryBuffer buf = MemoryBuffer.wrap(bas.toByteArray());
newObj = fory.deserialize(stream);
assertEquals(newObj, beanA);
newObj = fory.deserialize(buf);
@@ -238,7 +238,7 @@ public void testJavaOutputStream() throws IOException {
bas.flush();
ByteArrayInputStream bis = new ByteArrayInputStream(bas.toByteArray());
ForyInputStream stream = of(bis);
- MemoryBuffer buf = MemoryBuffer.fromByteArray(bas.toByteArray());
+ MemoryBuffer buf = MemoryBuffer.wrap(bas.toByteArray());
Object newObj = fory.deserializeJavaObject(stream, BeanA.class);
assertEquals(newObj, beanA);
newObj = fory.deserializeJavaObject(buf, BeanA.class);
@@ -255,7 +255,7 @@ public void testJavaOutputStream() throws IOException {
bas.flush();
ByteArrayInputStream bis = new ByteArrayInputStream(bas.toByteArray());
ForyInputStream stream = of(bis);
- MemoryBuffer buf = MemoryBuffer.fromByteArray(bas.toByteArray());
+ MemoryBuffer buf = MemoryBuffer.wrap(bas.toByteArray());
Object newObj = fory.deserializeJavaObjectAndClass(stream);
assertEquals(newObj, beanA);
newObj = fory.deserializeJavaObjectAndClass(buf);
@@ -269,7 +269,7 @@ public void testJavaOutputStream() throws IOException {
// test reader buffer grow
bis = new ByteArrayInputStream(bas.toByteArray());
stream = of(bis);
- buf = MemoryBuffer.fromByteArray(bas.toByteArray());
+ buf = MemoryBuffer.wrap(bas.toByteArray());
newObj = fory.deserializeJavaObjectAndClass(stream);
assertEquals(newObj, beanA);
newObj = fory.deserializeJavaObjectAndClass(buf);
diff --git a/java/fory-core/src/test/java/org/apache/fory/builder/CodecUtilsTest.java b/java/fory-core/src/test/java/org/apache/fory/builder/CodecUtilsTest.java
index 540b4d611c..6909663e82 100644
--- a/java/fory-core/src/test/java/org/apache/fory/builder/CodecUtilsTest.java
+++ b/java/fory-core/src/test/java/org/apache/fory/builder/CodecUtilsTest.java
@@ -24,7 +24,6 @@
import org.apache.fory.Fory;
import org.apache.fory.config.Language;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.MemoryUtils;
import org.apache.fory.test.bean.BeanA;
import org.testng.annotations.Test;
@@ -45,11 +44,11 @@ public void loadOrGenObjectCodecClass() throws Exception {
.asSubclass(Generated.GeneratedSerializer.class)
.getConstructor(Fory.class, Class.class)
.newInstance(fory, BeanA.class);
- MemoryBuffer buffer = MemoryUtils.buffer(32);
+ MemoryBuffer buffer = MemoryBuffer.buffer(32);
BeanA beanA = BeanA.createBeanA(2);
serializer.write(buffer, beanA);
byte[] bytes = buffer.getBytes(0, buffer.writerIndex());
- Object obj = serializer.read(MemoryUtils.wrap(bytes));
+ Object obj = serializer.read(MemoryBuffer.wrap(bytes));
assertEquals(obj, beanA);
}
}
diff --git a/java/fory-core/src/test/java/org/apache/fory/io/BlockedStreamUtilsTest.java b/java/fory-core/src/test/java/org/apache/fory/io/BlockedStreamUtilsTest.java
index f75a017d3d..5652e5d0d2 100644
--- a/java/fory-core/src/test/java/org/apache/fory/io/BlockedStreamUtilsTest.java
+++ b/java/fory-core/src/test/java/org/apache/fory/io/BlockedStreamUtilsTest.java
@@ -51,7 +51,7 @@ public void testDeserializeChannel() {
BlockedStreamUtils.serialize(fory, stream, foo);
BlockedStreamUtils.serializeJavaObject(fory, stream, foo);
try (MemoryBufferReadableChannel channel =
- new MemoryBufferReadableChannel(MemoryBuffer.fromByteArray(stream.toByteArray()))) {
+ new MemoryBufferReadableChannel(MemoryBuffer.wrap(stream.toByteArray()))) {
assertEquals(BlockedStreamUtils.deserialize(fory, channel), foo);
assertEquals(BlockedStreamUtils.deserializeJavaObject(fory, channel, Foo.class), foo);
}
diff --git a/java/fory-core/src/test/java/org/apache/fory/io/MemoryBufferObjectInputTest.java b/java/fory-core/src/test/java/org/apache/fory/io/MemoryBufferObjectInputTest.java
index bd750c8cdd..df5f5693ce 100644
--- a/java/fory-core/src/test/java/org/apache/fory/io/MemoryBufferObjectInputTest.java
+++ b/java/fory-core/src/test/java/org/apache/fory/io/MemoryBufferObjectInputTest.java
@@ -26,7 +26,6 @@
import org.apache.fory.Fory;
import org.apache.fory.ForyTestBase;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.MemoryUtils;
import org.testng.annotations.Test;
public class MemoryBufferObjectInputTest extends ForyTestBase {
@@ -34,7 +33,7 @@ public class MemoryBufferObjectInputTest extends ForyTestBase {
@Test(dataProvider = "compressNumber")
public void testForyObjectInput(boolean compressNumber) throws IOException {
Fory fory = Fory.builder().withNumberCompressed(compressNumber).build();
- MemoryBuffer buffer = MemoryUtils.buffer(32);
+ MemoryBuffer buffer = MemoryBuffer.buffer(32);
buffer.writeByte(1);
if (compressNumber) {
buffer.writeVarInt32(2);
diff --git a/java/fory-core/src/test/java/org/apache/fory/io/MemoryBufferObjectOutputTest.java b/java/fory-core/src/test/java/org/apache/fory/io/MemoryBufferObjectOutputTest.java
index 86645ddfa7..5ad709bd32 100644
--- a/java/fory-core/src/test/java/org/apache/fory/io/MemoryBufferObjectOutputTest.java
+++ b/java/fory-core/src/test/java/org/apache/fory/io/MemoryBufferObjectOutputTest.java
@@ -25,7 +25,6 @@
import java.io.IOException;
import org.apache.fory.Fory;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.MemoryUtils;
import org.testng.annotations.Test;
public class MemoryBufferObjectOutputTest {
@@ -33,7 +32,7 @@ public class MemoryBufferObjectOutputTest {
@Test
public void testForyObjectOutput() throws IOException {
Fory fory = Fory.builder().build();
- MemoryBuffer buffer = MemoryUtils.buffer(32);
+ MemoryBuffer buffer = MemoryBuffer.buffer(32);
try (MemoryBufferObjectOutput output = new MemoryBufferObjectOutput(fory, buffer)) {
output.writeByte(1);
output.writeInt(2);
diff --git a/java/fory-core/src/test/java/org/apache/fory/memory/BitUtilsTest.java b/java/fory-core/src/test/java/org/apache/fory/memory/BitUtilsTest.java
index 5e5e16217c..9cb7918b10 100644
--- a/java/fory-core/src/test/java/org/apache/fory/memory/BitUtilsTest.java
+++ b/java/fory-core/src/test/java/org/apache/fory/memory/BitUtilsTest.java
@@ -30,7 +30,7 @@ public class BitUtilsTest {
@Test
public void anyUnSet() {
int valueCount = 10;
- MemoryBuffer buffer = MemoryUtils.buffer(valueCount);
+ MemoryBuffer buffer = MemoryBuffer.buffer(valueCount);
int i = 0;
BitUtils.set(buffer, 0, i++);
BitUtils.set(buffer, 0, i++);
@@ -49,7 +49,7 @@ public void anyUnSet() {
@Test
public void getNullCount() {
int valueCount = 14;
- MemoryBuffer buffer = MemoryUtils.buffer(valueCount);
+ MemoryBuffer buffer = MemoryBuffer.buffer(valueCount);
buffer.putByte(0, (byte) 0b11000000);
assertEquals(BitUtils.getNullCount(buffer, 0, 8), 6);
}
@@ -57,7 +57,7 @@ public void getNullCount() {
@Test
public void testSetAll() {
int valueCount = 10;
- MemoryBuffer buffer = MemoryUtils.buffer(8);
+ MemoryBuffer buffer = MemoryBuffer.buffer(8);
BitUtils.setAll(buffer, 0, valueCount);
assertEquals(BitUtils.getNullCount(buffer, 0, valueCount), 0);
assertEquals("ff03000000000000", StringUtils.encodeHexString(buffer.getRemainingBytes()));
diff --git a/java/fory-core/src/test/java/org/apache/fory/memory/MemoryBufferTest.java b/java/fory-core/src/test/java/org/apache/fory/memory/MemoryBufferTest.java
index 2a57bb13c3..d6c46f00fe 100644
--- a/java/fory-core/src/test/java/org/apache/fory/memory/MemoryBufferTest.java
+++ b/java/fory-core/src/test/java/org/apache/fory/memory/MemoryBufferTest.java
@@ -24,6 +24,7 @@
import java.nio.ByteBuffer;
import java.util.Random;
+import org.apache.fory.type.Types;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -31,7 +32,7 @@ public class MemoryBufferTest {
@Test
public void testBufferPut() {
- MemoryBuffer buffer = MemoryUtils.buffer(16);
+ MemoryBuffer buffer = MemoryBuffer.buffer(16);
buffer.putByte(0, (byte) 10);
assertEquals(buffer.getByte(0), (byte) 10);
buffer.putChar(0, 'a');
@@ -50,7 +51,7 @@ public void testBufferPut() {
@Test
public void testBufferWrite() {
- MemoryBuffer buffer = MemoryUtils.buffer(8);
+ MemoryBuffer buffer = MemoryBuffer.buffer(8);
buffer.writeBoolean(true);
buffer.writeByte(Byte.MIN_VALUE);
buffer.writeChar('a');
@@ -77,7 +78,7 @@ public void testBufferWrite() {
@Test
public void testBufferUnsafeWrite() {
{
- MemoryBuffer buffer = MemoryUtils.buffer(1024);
+ MemoryBuffer buffer = MemoryBuffer.buffer(1024);
byte[] heapMemory = buffer.getHeapMemory();
long pos = buffer.getUnsafeAddress();
assertEquals(buffer._unsafeWriterAddress(), pos);
@@ -106,7 +107,7 @@ public void testBufferUnsafeWrite() {
assertEquals(buffer.getByte((int) (pos - Platform.BYTE_ARRAY_OFFSET)), Byte.MIN_VALUE);
}
{
- MemoryBuffer buffer = MemoryUtils.buffer(1024);
+ MemoryBuffer buffer = MemoryBuffer.buffer(1024);
int index = 0;
buffer.putByte(index, Byte.MIN_VALUE);
index += 1;
@@ -139,13 +140,13 @@ public void testWrapBuffer() {
byte[] bytes = new byte[8];
int offset = 2;
bytes[offset] = 1;
- MemoryBuffer buffer = MemoryUtils.wrap(bytes, offset, 2);
+ MemoryBuffer buffer = new MemoryBuffer(bytes, offset, 2);
assertEquals(buffer.readByte(), bytes[offset]);
}
{
byte[] bytes = new byte[8];
int offset = 2;
- MemoryBuffer buffer = MemoryUtils.wrap(ByteBuffer.wrap(bytes, offset, 2));
+ MemoryBuffer buffer = MemoryBuffer.wrap(ByteBuffer.wrap(bytes, offset, 2));
assertEquals(buffer.readByte(), bytes[offset]);
}
{
@@ -153,7 +154,7 @@ public void testWrapBuffer() {
int offset = 2;
direct.put(offset, (byte) 1);
direct.position(offset);
- MemoryBuffer buffer = MemoryUtils.wrap(direct);
+ MemoryBuffer buffer = MemoryBuffer.wrap(direct);
assertEquals(buffer.readByte(), direct.get(offset));
}
}
@@ -163,7 +164,7 @@ public void testSliceAsByteBuffer() {
byte[] data = new byte[10];
new Random().nextBytes(data);
{
- MemoryBuffer buffer = MemoryUtils.wrap(data, 5, 5);
+ MemoryBuffer buffer = new MemoryBuffer(data, 5, 5);
assertEquals(buffer.sliceAsByteBuffer(), ByteBuffer.wrap(data, 5, 5));
}
{
@@ -171,25 +172,35 @@ public void testSliceAsByteBuffer() {
direct.put(data);
direct.flip();
direct.position(5);
- MemoryBuffer buffer = MemoryUtils.wrap(direct);
+ MemoryBuffer buffer = MemoryBuffer.wrap(direct);
assertEquals(buffer.sliceAsByteBuffer(), direct);
Assert.assertEquals(
ByteBufferUtil.getAddress(buffer.sliceAsByteBuffer()),
ByteBufferUtil.getAddress(direct) + 5);
}
{
- long address = 0;
+ long address = -1;
try {
- address = Platform.allocateMemory(10);
- ByteBuffer direct = ByteBufferUtil.wrapDirectBuffer(address, 10);
- direct.put(data);
- direct.flip();
- direct.position(5);
- MemoryBuffer buffer = MemoryUtils.wrap(direct);
- assertEquals(buffer.sliceAsByteBuffer(), direct);
- assertEquals(ByteBufferUtil.getAddress(buffer.sliceAsByteBuffer()), address + 5);
+ ByteBuffer direct;
+ if (Platform.IS_ANDROID) {
+ direct = ByteBuffer.allocateDirect(10);
+ direct.put(data);
+ direct.flip();
+ direct.position(5);
+ MemoryBuffer buffer = MemoryBuffer.wrap(direct);
+ assertEquals(buffer.sliceAsByteBuffer(), direct);
+ } else {
+ address = Platform.allocateMemory(10);
+ direct = ByteBufferUtil.wrapDirectBuffer(address, 10);
+ direct.put(data);
+ direct.flip();
+ direct.position(5);
+ MemoryBuffer buffer = MemoryBuffer.wrap(direct);
+ assertEquals(buffer.sliceAsByteBuffer(), direct);
+ assertEquals(ByteBufferUtil.getAddress(buffer.sliceAsByteBuffer()), address + 5);
+ }
} finally {
- Platform.freeMemory(address);
+ if (address != -1) Platform.freeMemory(address);
}
}
}
@@ -207,8 +218,8 @@ public void testSliceAndGetRemainingBytes() {
@Test
public void testEqualTo() {
- MemoryBuffer buf1 = MemoryUtils.buffer(16);
- MemoryBuffer buf2 = MemoryUtils.buffer(16);
+ MemoryBuffer buf1 = MemoryBuffer.buffer(16);
+ MemoryBuffer buf2 = MemoryBuffer.buffer(16);
buf1.putInt64(0, 10);
buf2.putInt64(0, 10);
buf1.putByte(9, (byte) 1);
@@ -220,7 +231,7 @@ public void testEqualTo() {
@Test
public void testWritePrimitiveArrayWithSizeEmbedded() {
- MemoryBuffer buf = MemoryUtils.buffer(16);
+ MemoryBuffer buf = MemoryBuffer.buffer(16);
Random random = new Random(0);
byte[] bytes = new byte[100];
random.nextBytes(bytes);
@@ -228,12 +239,12 @@ public void testWritePrimitiveArrayWithSizeEmbedded() {
for (int i = 0; i < chars.length; i++) {
chars[i] = (char) random.nextInt();
}
- buf.writePrimitiveArrayWithSize(bytes, Platform.BYTE_ARRAY_OFFSET, bytes.length);
- buf.writePrimitiveArrayWithSize(chars, Platform.CHAR_ARRAY_OFFSET, chars.length * 2);
+ buf.writeArrayWithSize(bytes, 0, bytes.length, Types.JavaArray.BYTE);
+ buf.writeArrayWithSize(chars, 0, chars.length, Types.JavaArray.CHAR);
assertEquals(bytes, buf.readBytesAndSize());
assertEquals(chars, buf.readChars(buf.readVarUint32()));
- buf.writePrimitiveArrayAlignedSize(bytes, Platform.BYTE_ARRAY_OFFSET, bytes.length);
- buf.writePrimitiveArrayAlignedSize(chars, Platform.CHAR_ARRAY_OFFSET, chars.length * 2);
+ buf.writeArrayAlignedSize(bytes, 0, bytes.length, Types.JavaArray.BYTE);
+ buf.writeArrayAlignedSize(chars, 0, chars.length, Types.JavaArray.CHAR);
assertEquals(bytes, buf.readBytesWithAlignedSize());
assertEquals(chars, buf.readCharsWithAlignedSize());
}
@@ -241,7 +252,7 @@ public void testWritePrimitiveArrayWithSizeEmbedded() {
@Test
public void testWriteVarUint32() {
for (int i = 0; i < 32; i++) {
- MemoryBuffer buf = MemoryUtils.buffer(8);
+ MemoryBuffer buf = MemoryBuffer.buffer(8);
for (int j = 0; j < i; j++) {
buf.writeByte((byte) 1); // make address unaligned.
buf.readByte();
@@ -328,7 +339,7 @@ public void testWriteVarInt() {
}
private MemoryBuffer buf(int numUnaligned) {
- MemoryBuffer buf = MemoryUtils.buffer(1);
+ MemoryBuffer buf = MemoryBuffer.buffer(1);
for (int j = 0; j < numUnaligned; j++) {
buf.writeByte((byte) 1); // make address unaligned.
buf.readByte();
@@ -350,7 +361,7 @@ private void checkVarInt(MemoryBuffer buf, int value, int bytesWritten) {
@Test
public void testWriteVarInt64() {
- MemoryBuffer buf = MemoryUtils.buffer(8);
+ MemoryBuffer buf = MemoryBuffer.buffer(8);
checkVarInt64(buf, -1, 1);
for (int i = 0; i < 9; i++) {
for (int j = 0; j < i; j++) {
@@ -422,7 +433,7 @@ private void checkVarInt64(MemoryBuffer buf, long value, int bytesWritten) {
@Test
public void testWriteVarUint64() {
- MemoryBuffer buf = MemoryUtils.buffer(8);
+ MemoryBuffer buf = MemoryBuffer.buffer(8);
checkVarUint64(buf, -1, 9);
for (int i = 0; i < 9; i++) {
for (int j = 0; j < i; j++) {
@@ -490,7 +501,7 @@ private void checkVarUint64(MemoryBuffer buf, long value, int bytesWritten) {
@Test
public void testWriteVarUint32Aligned() {
- MemoryBuffer buf = MemoryUtils.buffer(16);
+ MemoryBuffer buf = MemoryBuffer.buffer(16);
assertEquals(buf.writeVarUint32Aligned(1), 4);
assertEquals(buf.readAlignedVarUint(), 1);
assertEquals(buf.writeVarUint32Aligned(1 << 5), 4);
@@ -514,10 +525,10 @@ public void testWriteVarUint32Aligned() {
buf.readInt16();
assertEquals(buf.readAlignedVarUint(), Integer.MAX_VALUE);
for (int i = 0; i < 32; i++) {
- MemoryBuffer buf1 = MemoryUtils.buffer(16);
+ MemoryBuffer buf1 = MemoryBuffer.buffer(16);
assertAligned(i, buf1);
}
- MemoryBuffer buf1 = MemoryUtils.buffer(16);
+ MemoryBuffer buf1 = MemoryBuffer.buffer(16);
for (int i = 0; i < 32; i++) {
assertAligned(i, buf1);
}
@@ -555,7 +566,7 @@ public void testGetShortB() {
@Test
public void testWriteSliInt64() {
- MemoryBuffer buf = MemoryUtils.buffer(8);
+ MemoryBuffer buf = MemoryBuffer.buffer(8);
checkSliInt64(buf, -1, 4);
for (int i = 0; i < 10; i++) {
for (int j = 0; j < i; j++) {
@@ -595,7 +606,7 @@ private void checkSliInt64(MemoryBuffer buf, long value, int bytesWritten) {
@Test
public void testVarUint32Small7() {
- MemoryBuffer buf = MemoryUtils.buffer(1);
+ MemoryBuffer buf = MemoryBuffer.buffer(1);
buf.writeVarUint32Small7(1);
assertEquals(buf.readVarUint32Small7(), 1);
assertEquals(buf.writeVarUint32Small7(127), 1);
@@ -612,7 +623,7 @@ public void testVarUint32Small7() {
@Test
public void testVarUint36Small() {
- MemoryBuffer buf = MemoryUtils.buffer(80);
+ MemoryBuffer buf = MemoryBuffer.buffer(80);
int index = 0;
{
int diff = LittleEndian.putVarUint36Small(buf.getHeapMemory(), index, 10);
@@ -661,7 +672,7 @@ public void testVarUint36Small() {
public void testReadBytesAsInt64() {
for (MemoryBuffer buffer :
new MemoryBuffer[] {
- MemoryUtils.buffer(16), MemoryUtils.wrap(ByteBuffer.allocateDirect(32)),
+ MemoryBuffer.buffer(16), MemoryBuffer.bufferDirect(32),
}) {
buffer.writeByte(10);
buffer.writeByte(20);
diff --git a/java/fory-core/src/test/java/org/apache/fory/meta/ClassDefEncoderTest.java b/java/fory-core/src/test/java/org/apache/fory/meta/ClassDefEncoderTest.java
index eec203fd96..c05d384ca6 100644
--- a/java/fory-core/src/test/java/org/apache/fory/meta/ClassDefEncoderTest.java
+++ b/java/fory-core/src/test/java/org/apache/fory/meta/ClassDefEncoderTest.java
@@ -58,8 +58,7 @@ public void testBigMetaEncoding() {
}) {
Fory fory = Fory.builder().withMetaShare(true).build();
ClassDef classDef = ClassDef.buildClassDef(fory, type);
- ClassDef classDef1 =
- ClassDef.readClassDef(fory, MemoryBuffer.fromByteArray(classDef.getEncoded()));
+ ClassDef classDef1 = ClassDef.readClassDef(fory, MemoryBuffer.wrap(classDef.getEncoded()));
Assert.assertEquals(classDef1, classDef);
}
}
@@ -75,8 +74,7 @@ public static class Foo2 extends Foo1 {}
public void testEmptySubClassSerializer() {
Fory fory = Fory.builder().withLanguage(Language.JAVA).requireClassRegistration(true).build();
ClassDef classDef = ClassDef.buildClassDef(fory, Foo2.class);
- ClassDef classDef1 =
- ClassDef.readClassDef(fory, MemoryBuffer.fromByteArray(classDef.getEncoded()));
+ ClassDef classDef1 = ClassDef.readClassDef(fory, MemoryBuffer.wrap(classDef.getEncoded()));
Assert.assertEquals(classDef, classDef1);
}
@@ -88,8 +86,7 @@ public void testBigClassNameObject() {
fory,
TestClassLengthTestClassLengthTestClassLengthTestClassLengthTestClassLengthTestClassLengthTestClassLength
.InnerClassTestLengthInnerClassTestLengthInnerClassTestLength.class);
- ClassDef classDef1 =
- ClassDef.readClassDef(fory, MemoryBuffer.fromByteArray(classDef.getEncoded()));
+ ClassDef classDef1 = ClassDef.readClassDef(fory, MemoryBuffer.wrap(classDef.getEncoded()));
Assert.assertEquals(classDef1, classDef);
}
diff --git a/java/fory-core/src/test/java/org/apache/fory/reflect/PlatformTest.java b/java/fory-core/src/test/java/org/apache/fory/reflect/PlatformTest.java
index 5befaafe76..947d0200bb 100644
--- a/java/fory-core/src/test/java/org/apache/fory/reflect/PlatformTest.java
+++ b/java/fory-core/src/test/java/org/apache/fory/reflect/PlatformTest.java
@@ -101,15 +101,20 @@ private boolean arrayEquals(byte[] bytes, byte[] bytes2) {
@Test
public void wrapDirectBuffer() {
- long address = 0;
+ long address = -1;
try {
int size = 16;
- address = Platform.allocateMemory(size);
- ByteBuffer buffer = ByteBufferUtil.wrapDirectBuffer(address, size);
+ ByteBuffer buffer;
+ if (Platform.IS_ANDROID) {
+ buffer = ByteBuffer.allocateDirect(size);
+ } else {
+ address = Platform.allocateMemory(size);
+ buffer = ByteBufferUtil.wrapDirectBuffer(address, size);
+ }
buffer.putLong(0, 1);
assertEquals(1, buffer.getLong(0));
} finally {
- Platform.freeMemory(address);
+ if (address != -1) Platform.freeMemory(address);
}
}
diff --git a/java/fory-core/src/test/java/org/apache/fory/resolver/ClassResolverTest.java b/java/fory-core/src/test/java/org/apache/fory/resolver/ClassResolverTest.java
index 1960466334..d9fc886cc3 100644
--- a/java/fory-core/src/test/java/org/apache/fory/resolver/ClassResolverTest.java
+++ b/java/fory-core/src/test/java/org/apache/fory/resolver/ClassResolverTest.java
@@ -51,7 +51,6 @@
import org.apache.fory.logging.Logger;
import org.apache.fory.logging.LoggerFactory;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.MemoryUtils;
import org.apache.fory.reflect.TypeRef;
import org.apache.fory.resolver.longlongpkg.C1;
import org.apache.fory.resolver.longlongpkg.C2;
@@ -229,7 +228,7 @@ public void testWriteClassName() {
.requireClassRegistration(false)
.build();
ClassResolver classResolver = fory.getClassResolver();
- MemoryBuffer buffer = MemoryUtils.buffer(32);
+ MemoryBuffer buffer = MemoryBuffer.buffer(32);
classResolver.writeClassInternal(buffer, getClass());
int writerIndex = buffer.writerIndex();
classResolver.writeClassInternal(buffer, getClass());
@@ -244,7 +243,7 @@ public void testWriteClassName() {
.requireClassRegistration(false)
.build();
ClassResolver classResolver = fory.getClassResolver();
- MemoryBuffer buffer = MemoryUtils.buffer(32);
+ MemoryBuffer buffer = MemoryBuffer.buffer(32);
classResolver.writeClassAndUpdateCache(buffer, getClass());
classResolver.writeClassAndUpdateCache(buffer, getClass());
Assert.assertSame(classResolver.readClassInfo(buffer).getCls(), getClass());
diff --git a/java/fory-core/src/test/java/org/apache/fory/resolver/MetaStringResolverTest.java b/java/fory-core/src/test/java/org/apache/fory/resolver/MetaStringResolverTest.java
index b9d393534c..9e739721c0 100644
--- a/java/fory-core/src/test/java/org/apache/fory/resolver/MetaStringResolverTest.java
+++ b/java/fory-core/src/test/java/org/apache/fory/resolver/MetaStringResolverTest.java
@@ -22,9 +22,7 @@
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
-import java.nio.ByteBuffer;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.MemoryUtils;
import org.apache.fory.meta.MetaString;
import org.apache.fory.meta.MetaStringEncoder;
import org.apache.fory.util.StringUtils;
@@ -34,7 +32,7 @@ public class MetaStringResolverTest {
@Test
public void testWriteMetaString() {
- MemoryBuffer buffer = MemoryUtils.buffer(32);
+ MemoryBuffer buffer = MemoryBuffer.buffer(32);
String str = StringUtils.random(128, 0);
MetaStringResolver stringResolver = new MetaStringResolver();
for (int i = 0; i < 128; i++) {
@@ -54,7 +52,7 @@ public void testWriteMetaString() {
public void testWriteSmallMetaString() {
for (MemoryBuffer buffer :
new MemoryBuffer[] {
- MemoryUtils.buffer(32), MemoryUtils.wrap(ByteBuffer.allocateDirect(32)),
+ MemoryBuffer.buffer(32), MemoryBuffer.bufferDirect(32),
}) {
for (int i = 0; i < 32; i++) {
String str = StringUtils.random(i, 0);
diff --git a/java/fory-core/src/test/java/org/apache/fory/serializer/CodegenSerializerTest.java b/java/fory-core/src/test/java/org/apache/fory/serializer/CodegenSerializerTest.java
index 6a274c25e2..0e99006b79 100644
--- a/java/fory-core/src/test/java/org/apache/fory/serializer/CodegenSerializerTest.java
+++ b/java/fory-core/src/test/java/org/apache/fory/serializer/CodegenSerializerTest.java
@@ -37,7 +37,6 @@
import org.apache.fory.config.CompatibleMode;
import org.apache.fory.config.Language;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.MemoryUtils;
import org.apache.fory.test.bean.Cyclic;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -88,7 +87,7 @@ public void testSerializeCircularReference() {
.withRefTracking(true)
.requireClassRegistration(false)
.build();
- MemoryBuffer buffer = MemoryUtils.buffer(32);
+ MemoryBuffer buffer = MemoryBuffer.buffer(32);
fory.serialize(buffer, cyclic);
fory.deserialize(buffer);
diff --git a/java/fory-core/src/test/java/org/apache/fory/serializer/DuplicateFieldsTest.java b/java/fory-core/src/test/java/org/apache/fory/serializer/DuplicateFieldsTest.java
index 3dcbf219cf..6b3c05d2fe 100644
--- a/java/fory-core/src/test/java/org/apache/fory/serializer/DuplicateFieldsTest.java
+++ b/java/fory-core/src/test/java/org/apache/fory/serializer/DuplicateFieldsTest.java
@@ -30,7 +30,6 @@
import org.apache.fory.config.ForyBuilder;
import org.apache.fory.config.Language;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.MemoryUtils;
import org.testng.annotations.Test;
public class DuplicateFieldsTest extends ForyTestBase {
@@ -64,7 +63,7 @@ public void testDuplicateFieldsNoCompatible() {
.build();
{
ObjectSerializer serializer = new ObjectSerializer<>(fory, C.class);
- MemoryBuffer buffer = MemoryUtils.buffer(32);
+ MemoryBuffer buffer = MemoryBuffer.buffer(32);
serializer.write(buffer, c);
C newC = serializer.read(buffer);
assertEquals(newC.f1, c.f1);
@@ -75,7 +74,7 @@ public void testDuplicateFieldsNoCompatible() {
Serializer serializer =
Serializers.newSerializer(
fory, C.class, CodecUtils.loadOrGenObjectCodecClass(C.class, fory));
- MemoryBuffer buffer = MemoryUtils.buffer(32);
+ MemoryBuffer buffer = MemoryBuffer.buffer(32);
serializer.write(buffer, c);
C newC = serializer.read(buffer);
assertEquals(newC.f1, c.f1);
@@ -116,7 +115,7 @@ public void testDuplicateFieldsCompatible(boolean scopedMetaShare) {
Fory fory = builder.build();
{
CompatibleSerializer serializer = new CompatibleSerializer<>(fory, C.class);
- MemoryBuffer buffer = MemoryUtils.buffer(32);
+ MemoryBuffer buffer = MemoryBuffer.buffer(32);
serializer.write(buffer, c);
C newC = serializer.read(buffer);
assertEquals(newC.f1, c.f1);
@@ -127,7 +126,7 @@ public void testDuplicateFieldsCompatible(boolean scopedMetaShare) {
Serializer serializer =
Serializers.newSerializer(
fory, C.class, CodecUtils.loadOrGenCompatibleCodecClass(C.class, fory));
- MemoryBuffer buffer = MemoryUtils.buffer(32);
+ MemoryBuffer buffer = MemoryBuffer.buffer(32);
serializer.write(buffer, c);
C newC = serializer.read(buffer);
assertEquals(newC.f1, c.f1);
diff --git a/java/fory-core/src/test/java/org/apache/fory/serializer/ObjectSerializerTest.java b/java/fory-core/src/test/java/org/apache/fory/serializer/ObjectSerializerTest.java
index 15cc87d4f7..a369a16ca6 100644
--- a/java/fory-core/src/test/java/org/apache/fory/serializer/ObjectSerializerTest.java
+++ b/java/fory-core/src/test/java/org/apache/fory/serializer/ObjectSerializerTest.java
@@ -27,7 +27,6 @@
import org.apache.fory.ForyTestBase;
import org.apache.fory.config.Language;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.MemoryUtils;
import org.apache.fory.test.bean.Cyclic;
import org.apache.fory.util.Preconditions;
import org.testng.Assert;
@@ -51,7 +50,7 @@ public String foo(String s) {
.requireClassRegistration(false)
.build();
ObjectSerializer serializer = new ObjectSerializer(fory, Foo.class);
- MemoryBuffer buffer = MemoryUtils.buffer(32);
+ MemoryBuffer buffer = MemoryBuffer.buffer(32);
Foo foo = new Foo();
serializer.write(buffer, foo);
Object obj = serializer.read(buffer);
@@ -95,7 +94,7 @@ public String foo(String s) {
.requireClassRegistration(false)
.build();
ObjectSerializer serializer = new ObjectSerializer(fory, foo.getClass());
- MemoryBuffer buffer = MemoryUtils.buffer(32);
+ MemoryBuffer buffer = MemoryBuffer.buffer(32);
serializer.write(buffer, foo);
Object obj = serializer.read(buffer);
assertEquals(foo.foo("str"), ((Foo) obj).foo("str"));
@@ -131,7 +130,7 @@ public void testSerializeCircularReference() {
.withRefTracking(true)
.requireClassRegistration(false)
.build();
- MemoryBuffer buffer = MemoryUtils.buffer(32);
+ MemoryBuffer buffer = MemoryBuffer.buffer(32);
ObjectSerializer serializer = new ObjectSerializer<>(fory, Cyclic.class);
fory.getRefResolver().writeRefOrNull(buffer, cyclic);
@@ -172,7 +171,7 @@ public void testSerialization() {
.withRefTracking(false)
.requireClassRegistration(false)
.build();
- MemoryBuffer buffer = MemoryUtils.buffer(32);
+ MemoryBuffer buffer = MemoryBuffer.buffer(32);
ObjectSerializer serializer = new ObjectSerializer<>(fory, A.class);
A a = new A();
serializer.write(buffer, a);
diff --git a/java/fory-core/src/test/java/org/apache/fory/serializer/StringSerializerTest.java b/java/fory-core/src/test/java/org/apache/fory/serializer/StringSerializerTest.java
index 436180ebe3..e32fdcdab4 100644
--- a/java/fory-core/src/test/java/org/apache/fory/serializer/StringSerializerTest.java
+++ b/java/fory-core/src/test/java/org/apache/fory/serializer/StringSerializerTest.java
@@ -23,7 +23,6 @@
import static org.testng.Assert.assertEquals;
import java.lang.reflect.Field;
-import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.concurrent.ArrayBlockingQueue;
@@ -35,9 +34,9 @@
import org.apache.fory.collection.Tuple2;
import org.apache.fory.config.Language;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.MemoryUtils;
import org.apache.fory.memory.Platform;
import org.apache.fory.reflect.ReflectionUtils;
+import org.apache.fory.type.Types;
import org.apache.fory.util.MathUtils;
import org.apache.fory.util.StringUtils;
import org.testng.Assert;
@@ -139,13 +138,13 @@ static void writeJDK8String(MemoryBuffer buffer, String value) {
final char[] chars =
(char[]) Platform.getObject(value, ReflectionUtils.getFieldOffset(String.class, "value"));
int numBytes = MathUtils.doubleExact(value.length());
- buffer.writePrimitiveArrayWithSize(chars, Platform.CHAR_ARRAY_OFFSET, numBytes);
+ buffer.writeArrayWithSize(chars, 0, value.length(), Types.JavaArray.CHAR);
}
@Test
public void testJavaStringSimple() {
Fory fory = Fory.builder().withStringCompressed(true).requireClassRegistration(false).build();
- MemoryBuffer buffer = MemoryUtils.buffer(32);
+ MemoryBuffer buffer = MemoryBuffer.buffer(32);
StringSerializer serializer = new StringSerializer(fory);
{
String str = "str";
@@ -211,7 +210,7 @@ public void testJavaString(boolean stringCompress, boolean writeNumUtf16BytesFor
.withWriteNumUtf16BytesForUtf8Encoding(writeNumUtf16BytesForUtf8Encoding)
.requireClassRegistration(false)
.build();
- MemoryBuffer buffer = MemoryUtils.buffer(32);
+ MemoryBuffer buffer = MemoryBuffer.buffer(32);
StringSerializer serializer = new StringSerializer(fory);
String longStr = new String(new char[50]).replace("\0", "abc");
@@ -237,7 +236,7 @@ public void testJavaStringOffHeap(
.withWriteNumUtf16BytesForUtf8Encoding(writeNumUtf16BytesForUtf8Encoding)
.requireClassRegistration(false)
.build();
- MemoryBuffer buffer = MemoryUtils.wrap(ByteBuffer.allocateDirect(1024));
+ MemoryBuffer buffer = MemoryBuffer.bufferDirect(1024);
Object o1 = "你好, Fory" + StringUtils.random(64);
Object o2 =
new String[] {"你好, Fory" + StringUtils.random(64), "你好, Fory" + StringUtils.random(64)};
@@ -340,7 +339,7 @@ public void testCompressJava8String() {
char[] utf16StrChars = utf16Str.toCharArray();
for (MemoryBuffer buffer :
new MemoryBuffer[] {
- MemoryUtils.buffer(512), MemoryUtils.wrap(ByteBuffer.allocateDirect(512)),
+ MemoryBuffer.buffer(512), MemoryBuffer.bufferDirect(512),
}) {
stringSerializer.writeJavaString(buffer, utf16Str);
assertEquals(stringSerializer.readJavaString(buffer), utf16Str);
@@ -363,7 +362,7 @@ public void testReadUtf8String(boolean writeNumUtf16BytesForUtf8Encoding) {
.build();
for (MemoryBuffer buffer :
new MemoryBuffer[] {
- MemoryUtils.buffer(32), MemoryUtils.wrap(ByteBuffer.allocateDirect(2048))
+ MemoryBuffer.buffer(32), MemoryBuffer.bufferDirect(2048),
}) {
StringSerializer serializer = new StringSerializer(fory);
serializer.write(buffer, "abc你好");
diff --git a/java/fory-core/src/test/java/org/apache/fory/serializer/collection/CollectionSerializersTest.java b/java/fory-core/src/test/java/org/apache/fory/serializer/collection/CollectionSerializersTest.java
index d2fcc0a1aa..dc5ba81eb4 100644
--- a/java/fory-core/src/test/java/org/apache/fory/serializer/collection/CollectionSerializersTest.java
+++ b/java/fory-core/src/test/java/org/apache/fory/serializer/collection/CollectionSerializersTest.java
@@ -64,7 +64,6 @@
import org.apache.fory.ForyTestBase;
import org.apache.fory.config.Language;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.MemoryUtils;
import org.apache.fory.reflect.TypeRef;
import org.apache.fory.serializer.collection.CollectionSerializers.JDKCompatibleCollectionSerializer;
import org.apache.fory.test.bean.Cyclic;
@@ -786,7 +785,7 @@ public void testJavaSerialization() {
.withRefTracking(false)
.requireClassRegistration(false)
.build();
- MemoryBuffer buffer = MemoryUtils.buffer(32);
+ MemoryBuffer buffer = MemoryBuffer.buffer(32);
JDKCompatibleCollectionSerializer javaSerializer =
new JDKCompatibleCollectionSerializer(fory, setClass);
javaSerializer.write(buffer, set);
diff --git a/java/fory-core/src/test/java/org/apache/fory/serializer/collection/SynchronizedSerializersTest.java b/java/fory-core/src/test/java/org/apache/fory/serializer/collection/SynchronizedSerializersTest.java
index 2215ce4640..45fc973dc7 100644
--- a/java/fory-core/src/test/java/org/apache/fory/serializer/collection/SynchronizedSerializersTest.java
+++ b/java/fory-core/src/test/java/org/apache/fory/serializer/collection/SynchronizedSerializersTest.java
@@ -39,7 +39,6 @@
import org.apache.fory.ForyTestBase;
import org.apache.fory.config.Language;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.MemoryUtils;
import org.apache.fory.memory.Platform;
import org.apache.fory.reflect.ReflectionUtils;
import org.apache.fory.serializer.Serializer;
@@ -58,7 +57,7 @@ public class SynchronizedSerializersTest extends ForyTestBase {
@Test
public void testWrite() throws Exception {
Fory fory = Fory.builder().withLanguage(Language.JAVA).requireClassRegistration(false).build();
- MemoryBuffer buffer = MemoryUtils.buffer(32);
+ MemoryBuffer buffer = MemoryBuffer.buffer(32);
Object[] values =
new Object[] {
Collections.synchronizedCollection(Collections.singletonList("abc")),
diff --git a/java/fory-core/src/test/java/org/apache/fory/serializer/collection/UnmodifiableSerializersTest.java b/java/fory-core/src/test/java/org/apache/fory/serializer/collection/UnmodifiableSerializersTest.java
index 0275c5a9e3..e50c2accf7 100644
--- a/java/fory-core/src/test/java/org/apache/fory/serializer/collection/UnmodifiableSerializersTest.java
+++ b/java/fory-core/src/test/java/org/apache/fory/serializer/collection/UnmodifiableSerializersTest.java
@@ -45,7 +45,6 @@
import org.apache.fory.ForyTestBase;
import org.apache.fory.config.Language;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.MemoryUtils;
import org.apache.fory.memory.Platform;
import org.apache.fory.reflect.ReflectionUtils;
import org.apache.fory.serializer.Serializer;
@@ -66,7 +65,7 @@ public class UnmodifiableSerializersTest extends ForyTestBase {
@Test
public void testWrite() throws Exception {
Fory fory = Fory.builder().withLanguage(Language.JAVA).requireClassRegistration(false).build();
- MemoryBuffer buffer = MemoryUtils.buffer(32);
+ MemoryBuffer buffer = MemoryBuffer.buffer(32);
Object[] values =
new Object[] {
Collections.unmodifiableCollection(Collections.singletonList("abc")),
diff --git a/java/fory-format/src/main/java/org/apache/fory/format/encoder/Encoders.java b/java/fory-format/src/main/java/org/apache/fory/format/encoder/Encoders.java
index 18845507b8..44484e2c0e 100644
--- a/java/fory-format/src/main/java/org/apache/fory/format/encoder/Encoders.java
+++ b/java/fory-format/src/main/java/org/apache/fory/format/encoder/Encoders.java
@@ -47,7 +47,6 @@
import org.apache.fory.logging.Logger;
import org.apache.fory.logging.LoggerFactory;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.MemoryUtils;
import org.apache.fory.reflect.TypeRef;
import org.apache.fory.type.TypeResolutionContext;
import org.apache.fory.type.TypeUtils;
@@ -90,7 +89,7 @@ public T fromRow(BinaryRow row) {
@Override
public BinaryRow toRow(T obj) {
- writer.setBuffer(MemoryUtils.buffer(initialBufferSize));
+ writer.setBuffer(MemoryBuffer.buffer(initialBufferSize));
writer.reset();
return encoder.toRow(obj);
}
@@ -155,7 +154,7 @@ public static RowEncoder bean(Class beanClass, BinaryRowWriter writer,
long schemaHash = DataTypes.computeSchemaHash(schema);
return new RowEncoder() {
- private final MemoryBuffer buffer = MemoryUtils.buffer(16);
+ private final MemoryBuffer buffer = MemoryBuffer.buffer(16);
@Override
public Schema schema() {
@@ -196,7 +195,7 @@ public T decode(MemoryBuffer buffer, int size) {
@Override
public T decode(byte[] bytes) {
- return decode(MemoryUtils.wrap(bytes), bytes.length);
+ return decode(MemoryBuffer.wrap(bytes), bytes.length);
}
@Override
@@ -405,7 +404,7 @@ public T decode(MemoryBuffer buffer, int size) {
@Override
public T decode(byte[] bytes) {
- return decode(MemoryUtils.wrap(bytes), bytes.length);
+ return decode(MemoryBuffer.wrap(bytes), bytes.length);
}
@Override
@@ -547,7 +546,7 @@ public T decode(MemoryBuffer buffer, int size) {
@Override
public T decode(byte[] bytes) {
- return decode(MemoryUtils.wrap(bytes), bytes.length);
+ return decode(MemoryBuffer.wrap(bytes), bytes.length);
}
@Override
diff --git a/java/fory-format/src/main/java/org/apache/fory/format/row/binary/BinaryArray.java b/java/fory-format/src/main/java/org/apache/fory/format/row/binary/BinaryArray.java
index 076f2a1b40..ea8cd00711 100644
--- a/java/fory-format/src/main/java/org/apache/fory/format/row/binary/BinaryArray.java
+++ b/java/fory-format/src/main/java/org/apache/fory/format/row/binary/BinaryArray.java
@@ -33,8 +33,8 @@
import org.apache.fory.format.type.DataTypes;
import org.apache.fory.memory.BitUtils;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.MemoryUtils;
import org.apache.fory.memory.Platform;
+import org.apache.fory.type.Types;
import org.apache.fory.util.Preconditions;
/**
@@ -156,49 +156,56 @@ public void setDecimal(int ordinal, BigDecimal value) {
public boolean[] toBooleanArray() {
boolean[] values = new boolean[numElements];
- buffer.copyToUnsafe(elementOffset, values, Platform.BOOLEAN_ARRAY_OFFSET, numElements);
+ // buffer.copyToUnsafe(elementOffset, values, Platform.BOOLEAN_ARRAY_OFFSET, numElements);
+ buffer.copyTo(elementOffset, values, 0, numElements, Types.JavaArray.BOOL, false);
return values;
}
public byte[] toByteArray() {
byte[] values = new byte[numElements];
- buffer.copyToUnsafe(elementOffset, values, Platform.BYTE_ARRAY_OFFSET, numElements);
+ // buffer.copyToUnsafe(elementOffset, values, Platform.BYTE_ARRAY_OFFSET, numElements);
+ buffer.copyTo(elementOffset, values, 0, numElements, Types.JavaArray.BYTE, false);
return values;
}
public short[] toShortArray() {
short[] values = new short[numElements];
- buffer.copyToUnsafe(elementOffset, values, Platform.SHORT_ARRAY_OFFSET, numElements * 2);
+ // buffer.copyToUnsafe(elementOffset, values, Platform.SHORT_ARRAY_OFFSET, numElements * 2);
+ buffer.copyTo(elementOffset, values, 0, numElements, Types.JavaArray.SHORT, false);
return values;
}
public int[] toIntArray() {
int[] values = new int[numElements];
- buffer.copyToUnsafe(elementOffset, values, Platform.INT_ARRAY_OFFSET, numElements * 4);
+ // buffer.copyToUnsafe(elementOffset, values, Platform.INT_ARRAY_OFFSET, numElements * 4);
+ buffer.copyTo(elementOffset, values, 0, numElements, Types.JavaArray.INT, false);
return values;
}
public long[] toLongArray() {
long[] values = new long[numElements];
- buffer.copyToUnsafe(elementOffset, values, Platform.LONG_ARRAY_OFFSET, numElements * 8);
+ // buffer.copyToUnsafe(elementOffset, values, Platform.LONG_ARRAY_OFFSET, numElements * 8);
+ buffer.copyTo(elementOffset, values, 0, numElements, Types.JavaArray.LONG, false);
return values;
}
public float[] toFloatArray() {
float[] values = new float[numElements];
- buffer.copyToUnsafe(elementOffset, values, Platform.FLOAT_ARRAY_OFFSET, numElements * 4);
+ // buffer.copyToUnsafe(elementOffset, values, Platform.FLOAT_ARRAY_OFFSET, numElements * 4);
+ buffer.copyTo(elementOffset, values, 0, numElements, Types.JavaArray.FLOAT, false);
return values;
}
public double[] toDoubleArray() {
double[] values = new double[numElements];
- buffer.copyToUnsafe(elementOffset, values, Platform.DOUBLE_ARRAY_OFFSET, numElements * 8);
+ // buffer.copyToUnsafe(elementOffset, values, Platform.DOUBLE_ARRAY_OFFSET, numElements * 8);
+ buffer.copyTo(elementOffset, values, 0, numElements, Types.JavaArray.DOUBLE, false);
return values;
}
@Override
public ArrayData copy() {
- MemoryBuffer copyBuf = MemoryUtils.buffer(sizeInBytes);
+ MemoryBuffer copyBuf = MemoryBuffer.buffer(sizeInBytes);
buffer.copyTo(baseOffset, copyBuf, 0, sizeInBytes);
BinaryArray arrayCopy = new BinaryArray(field);
arrayCopy.pointTo(copyBuf, 0, sizeInBytes);
@@ -235,7 +242,7 @@ private static BinaryArray fromPrimitiveArray(Object arr, int offset, int length
Platform.copyMemory(
arr, offset, data, Platform.BYTE_ARRAY_OFFSET + headerInBytes, valueRegionInBytes);
- MemoryBuffer memoryBuffer = MemoryUtils.wrap(data);
+ MemoryBuffer memoryBuffer = MemoryBuffer.wrap(data);
result.pointTo(memoryBuffer, 0, (int) totalSize);
return result;
}
diff --git a/java/fory-format/src/main/java/org/apache/fory/format/row/binary/BinaryMap.java b/java/fory-format/src/main/java/org/apache/fory/format/row/binary/BinaryMap.java
index 4ff14f4122..aae2757ef0 100644
--- a/java/fory-format/src/main/java/org/apache/fory/format/row/binary/BinaryMap.java
+++ b/java/fory-format/src/main/java/org/apache/fory/format/row/binary/BinaryMap.java
@@ -24,8 +24,7 @@
import org.apache.fory.format.row.MapData;
import org.apache.fory.format.type.DataTypes;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.MemoryUtils;
-import org.apache.fory.memory.Platform;
+import org.apache.fory.type.Types;
/**
* An BinaryMap implementation of Map which is backed by two BinaryArray./ForyObjectOutput
@@ -109,15 +108,16 @@ public BinaryArray valueArray() {
@Override
public MapData copy() {
- MemoryBuffer copyBuf = MemoryUtils.buffer(sizeInBytes);
+ MemoryBuffer copyBuf = MemoryBuffer.buffer(sizeInBytes);
buf.copyTo(baseOffset, copyBuf, 0, sizeInBytes);
BinaryMap mapCopy = new BinaryMap(field);
mapCopy.pointTo(copyBuf, 0, sizeInBytes);
return mapCopy;
}
- public void writeToMemory(Object target, long targetOffset) {
- buf.copyToUnsafe(baseOffset, target, targetOffset, sizeInBytes);
+ public void writeToBytes(byte[] target, int targetOffset) {
+ // buf.copyToUnsafe(baseOffset, target, targetOffset, sizeInBytes);
+ buf.copyTo(baseOffset, target, targetOffset, sizeInBytes, Types.JavaArray.BYTE, false);
}
public void writeTo(ByteBuffer buffer) {
@@ -125,7 +125,7 @@ public void writeTo(ByteBuffer buffer) {
byte[] target = buffer.array();
int offset = buffer.arrayOffset();
int pos = buffer.position();
- writeToMemory(target, Platform.BYTE_ARRAY_OFFSET + offset + pos);
+ writeToBytes(target, offset + pos);
buffer.position(pos + sizeInBytes);
}
diff --git a/java/fory-format/src/main/java/org/apache/fory/format/row/binary/BinaryRow.java b/java/fory-format/src/main/java/org/apache/fory/format/row/binary/BinaryRow.java
index ad9f1384ff..07bf44d364 100644
--- a/java/fory-format/src/main/java/org/apache/fory/format/row/binary/BinaryRow.java
+++ b/java/fory-format/src/main/java/org/apache/fory/format/row/binary/BinaryRow.java
@@ -31,7 +31,6 @@
import org.apache.fory.format.type.DataTypes;
import org.apache.fory.memory.BitUtils;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.MemoryUtils;
import org.apache.fory.util.Preconditions;
/**
@@ -171,7 +170,7 @@ public BinaryMap getMap(int ordinal) {
@Override
public Row copy() {
- MemoryBuffer copyBuf = MemoryUtils.buffer(sizeInBytes);
+ MemoryBuffer copyBuf = MemoryBuffer.buffer(sizeInBytes);
buffer.copyTo(baseOffset, copyBuf, 0, sizeInBytes);
BinaryRow copyRow = new BinaryRow(schema);
copyRow.pointTo(copyBuf, 0, sizeInBytes);
diff --git a/java/fory-format/src/main/java/org/apache/fory/format/row/binary/UnsafeTrait.java b/java/fory-format/src/main/java/org/apache/fory/format/row/binary/UnsafeTrait.java
index ad7447e8b3..9f1803bbff 100644
--- a/java/fory-format/src/main/java/org/apache/fory/format/row/binary/UnsafeTrait.java
+++ b/java/fory-format/src/main/java/org/apache/fory/format/row/binary/UnsafeTrait.java
@@ -142,7 +142,7 @@ BigDecimal getDecimal(int ordinal, ArrowType.Decimal decimalType) {
}
MemoryBuffer buffer = getBuffer(ordinal);
ArrowBuf arrowBuf = ArrowUtils.decimalArrowBuf();
- buffer.copyToUnsafe(0, null, arrowBuf.memoryAddress(), DECIMAL_BYTE_LENGTH);
+ buffer.copyToDirectUnsafe(0, arrowBuf.memoryAddress(), DECIMAL_BYTE_LENGTH);
BigDecimal decimal =
DecimalUtility.getBigDecimalFromArrowBuf(
arrowBuf, 0, decimalType.getScale(), DECIMAL_BYTE_LENGTH);
diff --git a/java/fory-format/src/main/java/org/apache/fory/format/row/binary/writer/BinaryArrayWriter.java b/java/fory-format/src/main/java/org/apache/fory/format/row/binary/writer/BinaryArrayWriter.java
index 8627121724..adce6f3eec 100644
--- a/java/fory-format/src/main/java/org/apache/fory/format/row/binary/writer/BinaryArrayWriter.java
+++ b/java/fory-format/src/main/java/org/apache/fory/format/row/binary/writer/BinaryArrayWriter.java
@@ -33,8 +33,7 @@
import org.apache.fory.format.row.binary.BinaryArray;
import org.apache.fory.format.type.DataTypes;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.MemoryUtils;
-import org.apache.fory.memory.Platform;
+import org.apache.fory.type.Types.JavaArray;
/**
* Writer for binary array. See {@link BinaryArray}
@@ -56,7 +55,7 @@ public class BinaryArrayWriter extends BinaryWriter {
/** Must call reset before using writer constructed by this constructor. */
public BinaryArrayWriter(Field field) {
// buffer size can grow
- this(field, MemoryUtils.buffer(64));
+ this(field, MemoryBuffer.buffer(64));
super.startIndex = 0;
}
@@ -162,7 +161,8 @@ public void write(int ordinal, BigDecimal value) {
writeDecimal(ordinal, value, (ArrowType.Decimal) field.getChildren().get(0).getType());
}
- private void fromPrimitiveArray(Object arr, int offset, int numElements, Field type) {
+ private void fromPrimitiveArray(
+ Object arr, int offset, int numElements, Field type, JavaArray eleType) {
if (DataTypes.getTypeId(type.getChildren().get(0).getType())
!= DataTypes.getTypeId(this.field.getChildren().get(0).getType())) {
String msg =
@@ -171,38 +171,36 @@ private void fromPrimitiveArray(Object arr, int offset, int numElements, Field t
type.getChildren().get(0).getType(), this.field.getChildren().get(0).getType());
throw new IllegalArgumentException(msg);
}
- buffer.copyFromUnsafe(
- startIndex + headerInBytes, arr, offset, numElements * (long) elementSize);
- // no need to increasewriterIndex, because reset has already increased writerIndex
+ buffer.copyTo(startIndex + headerInBytes, arr, offset, numElements, eleType, false);
+ // no need to increase writerIndex, because reset has already increased writerIndex
}
public void fromPrimitiveArray(byte[] arr) {
- fromPrimitiveArray(arr, Platform.BYTE_ARRAY_OFFSET, arr.length, PRIMITIVE_BYTE_ARRAY_FIELD);
+ fromPrimitiveArray(arr, 0, arr.length, PRIMITIVE_BYTE_ARRAY_FIELD, JavaArray.BYTE);
}
public void fromPrimitiveArray(boolean[] arr) {
- fromPrimitiveArray(
- arr, Platform.BOOLEAN_ARRAY_OFFSET, arr.length, PRIMITIVE_BOOLEAN_ARRAY_FIELD);
+ fromPrimitiveArray(arr, 0, arr.length, PRIMITIVE_BOOLEAN_ARRAY_FIELD, JavaArray.BOOL);
}
public void fromPrimitiveArray(short[] arr) {
- fromPrimitiveArray(arr, Platform.SHORT_ARRAY_OFFSET, arr.length, PRIMITIVE_SHORT_ARRAY_FIELD);
+ fromPrimitiveArray(arr, 0, arr.length, PRIMITIVE_SHORT_ARRAY_FIELD, JavaArray.SHORT);
}
public void fromPrimitiveArray(int[] arr) {
- fromPrimitiveArray(arr, Platform.INT_ARRAY_OFFSET, arr.length, PRIMITIVE_INT_ARRAY_FIELD);
+ fromPrimitiveArray(arr, 0, arr.length, PRIMITIVE_INT_ARRAY_FIELD, JavaArray.INT);
}
public void fromPrimitiveArray(long[] arr) {
- fromPrimitiveArray(arr, Platform.LONG_ARRAY_OFFSET, arr.length, PRIMITIVE_LONG_ARRAY_FIELD);
+ fromPrimitiveArray(arr, 0, arr.length, PRIMITIVE_LONG_ARRAY_FIELD, JavaArray.LONG);
}
public void fromPrimitiveArray(float[] arr) {
- fromPrimitiveArray(arr, Platform.FLOAT_ARRAY_OFFSET, arr.length, PRIMITIVE_FLOAT_ARRAY_FIELD);
+ fromPrimitiveArray(arr, 0, arr.length, PRIMITIVE_FLOAT_ARRAY_FIELD, JavaArray.FLOAT);
}
public void fromPrimitiveArray(double[] arr) {
- fromPrimitiveArray(arr, Platform.DOUBLE_ARRAY_OFFSET, arr.length, PRIMITIVE_DOUBLE_ARRAY_FIELD);
+ fromPrimitiveArray(arr, 0, arr.length, PRIMITIVE_DOUBLE_ARRAY_FIELD, JavaArray.DOUBLE);
}
public BinaryArray toArray() {
diff --git a/java/fory-format/src/main/java/org/apache/fory/format/row/binary/writer/BinaryRowWriter.java b/java/fory-format/src/main/java/org/apache/fory/format/row/binary/writer/BinaryRowWriter.java
index 9cbd48d05d..1a6c0609d8 100644
--- a/java/fory-format/src/main/java/org/apache/fory/format/row/binary/writer/BinaryRowWriter.java
+++ b/java/fory-format/src/main/java/org/apache/fory/format/row/binary/writer/BinaryRowWriter.java
@@ -26,7 +26,6 @@
import org.apache.arrow.vector.types.pojo.Schema;
import org.apache.fory.format.row.binary.BinaryRow;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.MemoryUtils;
/**
* Writer to write data into buffer using row format, see {@link BinaryRow}.
@@ -44,7 +43,7 @@ public class BinaryRowWriter extends BinaryWriter {
private final int fixedSize;
public BinaryRowWriter(Schema schema) {
- super(MemoryUtils.buffer(schema.getFields().size() * 32), 0);
+ super(MemoryBuffer.buffer(schema.getFields().size() * 32), 0);
super.startIndex = 0;
this.schema = schema;
this.headerInBytes = calculateBitmapWidthInBytes(schema.getFields().size());
@@ -138,7 +137,7 @@ public BinaryRow getRow() {
public BinaryRow copyToRow() {
BinaryRow row = new BinaryRow(schema);
int size = size();
- MemoryBuffer buffer = MemoryUtils.buffer(size);
+ MemoryBuffer buffer = MemoryBuffer.buffer(size);
this.buffer.copyTo(startIndex, buffer, 0, size);
row.pointTo(buffer, startIndex, size);
return row;
diff --git a/java/fory-format/src/main/java/org/apache/fory/format/row/binary/writer/BinaryWriter.java b/java/fory-format/src/main/java/org/apache/fory/format/row/binary/writer/BinaryWriter.java
index d24d547ed8..b399aa2ebc 100644
--- a/java/fory-format/src/main/java/org/apache/fory/format/row/binary/writer/BinaryWriter.java
+++ b/java/fory-format/src/main/java/org/apache/fory/format/row/binary/writer/BinaryWriter.java
@@ -218,8 +218,8 @@ protected final void writeDecimal(int ordinal, BigDecimal value, ArrowType.Decim
ArrowBuf arrowBuf = ArrowUtils.buffer(DecimalUtils.DECIMAL_BYTE_LENGTH);
DecimalUtility.writeBigDecimalToArrowBuf(
value, arrowBuf, 0, DecimalUtils.DECIMAL_BYTE_LENGTH);
- buffer.copyFromUnsafe(
- writerIndex(), null, arrowBuf.memoryAddress(), DecimalUtils.DECIMAL_BYTE_LENGTH);
+ buffer.copyFromDirectUnsafe(
+ writerIndex(), arrowBuf.memoryAddress(), DecimalUtils.DECIMAL_BYTE_LENGTH);
arrowBuf.getReferenceManager().release();
setOffsetAndSize(ordinal, writerIndex(), DecimalUtils.DECIMAL_BYTE_LENGTH);
increaseWriterIndex(DecimalUtils.DECIMAL_BYTE_LENGTH);
diff --git a/java/fory-format/src/main/java/org/apache/fory/format/vectorized/ArrowSerializers.java b/java/fory-format/src/main/java/org/apache/fory/format/vectorized/ArrowSerializers.java
index 7f5828f7bc..374cc02dbe 100644
--- a/java/fory-format/src/main/java/org/apache/fory/format/vectorized/ArrowSerializers.java
+++ b/java/fory-format/src/main/java/org/apache/fory/format/vectorized/ArrowSerializers.java
@@ -35,7 +35,6 @@
import org.apache.fory.io.MemoryBufferWritableChannel;
import org.apache.fory.io.MockWritableChannel;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.MemoryUtils;
import org.apache.fory.memory.Platform;
import org.apache.fory.serializer.BufferObject;
import org.apache.fory.serializer.Serializers.CrossLanguageCompatibleSerializer;
@@ -118,7 +117,7 @@ private static void write(VectorSchemaRoot root, WritableByteChannel byteChannel
@Override
public MemoryBuffer toBuffer() {
- MemoryBuffer buffer = MemoryUtils.buffer(totalBytes);
+ MemoryBuffer buffer = MemoryBuffer.buffer(totalBytes);
write(root, new MemoryBufferWritableChannel(buffer));
return buffer.slice(0, buffer.writerIndex());
}
@@ -159,7 +158,7 @@ private static void write(ArrowTable table, WritableByteChannel byteChannel) {
@Override
public MemoryBuffer toBuffer() {
- MemoryBuffer buffer = MemoryUtils.buffer(totalBytes);
+ MemoryBuffer buffer = MemoryBuffer.buffer(totalBytes);
write(table, new MemoryBufferWritableChannel(buffer));
return buffer.slice(0, buffer.writerIndex());
}
diff --git a/java/fory-format/src/test/java/org/apache/fory/format/CrossLanguageTest.java b/java/fory-format/src/test/java/org/apache/fory/format/CrossLanguageTest.java
index 8fe07212ea..7f0363c101 100644
--- a/java/fory-format/src/test/java/org/apache/fory/format/CrossLanguageTest.java
+++ b/java/fory-format/src/test/java/org/apache/fory/format/CrossLanguageTest.java
@@ -65,7 +65,6 @@
import org.apache.fory.logging.Logger;
import org.apache.fory.logging.LoggerFactory;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.MemoryUtils;
import org.apache.fory.serializer.BufferObject;
import org.apache.fory.test.TestUtils;
import org.testng.Assert;
@@ -138,7 +137,7 @@ public void testSerializationWithoutSchema() throws IOException {
Assert.assertTrue(executeCommand(command, 30));
}
- MemoryBuffer buffer = MemoryUtils.wrap(Files.readAllBytes(dataFile));
+ MemoryBuffer buffer = MemoryBuffer.wrap(Files.readAllBytes(dataFile));
BinaryRow newRow = new BinaryRow(encoder.schema());
newRow.pointTo(buffer, 0, buffer.size());
Assert.assertEquals(foo, encoder.fromRow(newRow));
@@ -167,7 +166,7 @@ public void testSerializationWithSchema() throws IOException {
Assert.assertTrue(executeCommand(command, 30));
}
- MemoryBuffer buffer = MemoryUtils.wrap(Files.readAllBytes(dataFile));
+ MemoryBuffer buffer = MemoryBuffer.wrap(Files.readAllBytes(dataFile));
BinaryRow newRow = new BinaryRow(encoder.schema());
newRow.pointTo(buffer, 0, buffer.size());
Assert.assertEquals(foo, encoder.fromRow(newRow));
@@ -182,7 +181,7 @@ public void testRecordBatchBasic() throws IOException {
VectorSchemaRoot root =
new VectorSchemaRoot(Collections.singletonList(field), Collections.singletonList(vector));
Path dataFile = Files.createTempFile("foo", "data");
- MemoryBuffer buffer = MemoryUtils.buffer(128);
+ MemoryBuffer buffer = MemoryBuffer.buffer(128);
try (ArrowStreamWriter writer =
new ArrowStreamWriter(root, null, new MemoryBufferOutputStream(buffer))) {
writer.start();
@@ -213,7 +212,7 @@ public void testRecordBatchWriter() throws IOException {
Foo foo = Foo.create();
RowEncoder encoder = Encoders.bean(Foo.class);
Path dataFile = Files.createTempFile("foo", "data");
- MemoryBuffer buffer = MemoryUtils.buffer(128);
+ MemoryBuffer buffer = MemoryBuffer.buffer(128);
ImmutableList command =
ImmutableList.of(
PYTHON_EXECUTABLE,
@@ -272,7 +271,7 @@ public void testWriteMultiRecordBatch() throws IOException {
schemaFile.toAbsolutePath().toString(),
dataFile.toAbsolutePath().toString());
{
- MemoryBuffer buffer = MemoryUtils.buffer(128);
+ MemoryBuffer buffer = MemoryBuffer.buffer(128);
buffer.writerIndex(0);
DataTypes.serializeSchema(encoder.schema(), buffer);
Files.write(schemaFile, buffer.getBytes(0, buffer.writerIndex()));
@@ -286,7 +285,7 @@ public void testWriteMultiRecordBatch() throws IOException {
arrowWriter.write(row);
}
ArrowRecordBatch recordBatch = arrowWriter.finishAsRecordBatch();
- MemoryBuffer buffer = MemoryUtils.buffer(128);
+ MemoryBuffer buffer = MemoryBuffer.buffer(128);
ArrowUtils.serializeRecordBatch(recordBatch, buffer);
arrowWriter.reset();
Files.write(
@@ -358,7 +357,7 @@ public void testSerializeArrowInBand() throws Exception {
.requireClassRegistration(false)
.build();
ArrowSerializers.registerSerializers(fory);
- MemoryBuffer buffer = MemoryUtils.buffer(32);
+ MemoryBuffer buffer = MemoryBuffer.buffer(32);
int size = 2000;
VectorSchemaRoot root = createVectorSchemaRoot(size);
fory.serialize(buffer, root);
@@ -384,7 +383,7 @@ public void testSerializeArrowInBand() throws Exception {
dataFile.toAbsolutePath().toString());
Assert.assertTrue(executeCommand(command, 30));
- MemoryBuffer buffer2 = MemoryUtils.wrap(Files.readAllBytes(dataFile));
+ MemoryBuffer buffer2 = MemoryBuffer.wrap(Files.readAllBytes(dataFile));
assertRecordBatchEqual((VectorSchemaRoot) fory.deserialize(buffer2), root);
assertTableEqual((ArrowTable) fory.deserialize(buffer2), table);
}
@@ -400,7 +399,7 @@ public void testSerializeArrowOutOfBand() throws Exception {
.build();
ArrowSerializers.registerSerializers(fory);
- MemoryBuffer buffer = MemoryUtils.buffer(32);
+ MemoryBuffer buffer = MemoryBuffer.buffer(32);
int size = 2000;
VectorSchemaRoot root = createVectorSchemaRoot(size);
Schema schema = root.getSchema();
@@ -429,7 +428,7 @@ public void testSerializeArrowOutOfBand() throws Exception {
Files.write(intBandDataFile, buffer.getBytes(0, buffer.writerIndex()));
Path outOfBandDataFile =
Files.createTempFile("test_serialize_arrow_out_of_band", "out_of_band.data");
- MemoryBuffer outOfBandBuffer = MemoryUtils.buffer(32);
+ MemoryBuffer outOfBandBuffer = MemoryBuffer.buffer(32);
outOfBandBuffer.writeInt32(bufferObjects.get(0).totalBytes());
outOfBandBuffer.writeInt32(bufferObjects.get(1).totalBytes());
bufferObjects.get(0).writeTo(outOfBandBuffer);
@@ -445,8 +444,8 @@ public void testSerializeArrowOutOfBand() throws Exception {
outOfBandDataFile.toAbsolutePath().toString());
Assert.assertTrue(executeCommand(command, 30));
- MemoryBuffer intBandBuffer = MemoryUtils.wrap(Files.readAllBytes(intBandDataFile));
- outOfBandBuffer = MemoryUtils.wrap(Files.readAllBytes(outOfBandDataFile));
+ MemoryBuffer intBandBuffer = MemoryBuffer.wrap(Files.readAllBytes(intBandDataFile));
+ outOfBandBuffer = MemoryBuffer.wrap(Files.readAllBytes(outOfBandDataFile));
int len1 = outOfBandBuffer.readInt32();
int len2 = outOfBandBuffer.readInt32();
buffers = Arrays.asList(outOfBandBuffer.slice(8, len1), outOfBandBuffer.slice(8 + len1, len2));
diff --git a/java/fory-format/src/test/java/org/apache/fory/format/encoder/CustomCodecTest.java b/java/fory-format/src/test/java/org/apache/fory/format/encoder/CustomCodecTest.java
index 33b0faa4b2..9dd1d26e26 100644
--- a/java/fory-format/src/test/java/org/apache/fory/format/encoder/CustomCodecTest.java
+++ b/java/fory-format/src/test/java/org/apache/fory/format/encoder/CustomCodecTest.java
@@ -33,7 +33,6 @@
import org.apache.fory.format.row.binary.BinaryArray;
import org.apache.fory.format.row.binary.BinaryRow;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.MemoryUtils;
import org.apache.fory.reflect.TypeRef;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -106,7 +105,7 @@ public void testCustomTypes() {
bean.f4 = new CustomByteBuf3("f4 value".getBytes(StandardCharsets.UTF_8));
final RowEncoder encoder = Encoders.bean(CustomType.class);
final BinaryRow row = encoder.toRow(bean);
- final MemoryBuffer buffer = MemoryUtils.wrap(row.toBytes());
+ final MemoryBuffer buffer = MemoryBuffer.wrap(row.toBytes());
row.pointTo(buffer, 0, buffer.size());
final CustomType deserializedBean = encoder.fromRow(row);
Assert.assertEquals(deserializedBean, bean);
@@ -117,7 +116,7 @@ public void testNullFields() {
final CustomType bean = new CustomType();
final RowEncoder encoder = Encoders.bean(CustomType.class);
final BinaryRow row = encoder.toRow(bean);
- final MemoryBuffer buffer = MemoryUtils.wrap(row.toBytes());
+ final MemoryBuffer buffer = MemoryBuffer.wrap(row.toBytes());
row.pointTo(buffer, 0, buffer.size());
final CustomType deserializedBean = encoder.fromRow(row);
Assert.assertEquals(deserializedBean, bean);
@@ -131,7 +130,7 @@ public void testUuidFields() {
bean.f3 = new TreeSet<>(Arrays.asList(new UUID(7, 8), new UUID(9, 10)));
final RowEncoder encoder = Encoders.bean(UuidType.class);
final BinaryRow row = encoder.toRow(bean);
- final MemoryBuffer buffer = MemoryUtils.wrap(row.toBytes());
+ final MemoryBuffer buffer = MemoryBuffer.wrap(row.toBytes());
row.pointTo(buffer, 0, buffer.size());
final UuidType deserializedBean = encoder.fromRow(row);
Assert.assertEquals(deserializedBean, bean);
@@ -163,7 +162,7 @@ public TypeRef encodedType() {
static class CustomByteBufEncoder implements CustomCodec.MemoryBufferCodec {
@Override
public MemoryBuffer encode(final CustomByteBuf value) {
- return MemoryBuffer.fromByteArray(value.buf);
+ return MemoryBuffer.wrap(value.buf);
}
@Override
@@ -271,7 +270,7 @@ public void testCodecTypeInterception() {
final InterceptedType bean = new InterceptedTypeImpl(42);
final RowEncoder encoder = Encoders.bean(InterceptedType.class);
final BinaryRow row = encoder.toRow(bean);
- final MemoryBuffer buffer = MemoryUtils.wrap(row.toBytes());
+ final MemoryBuffer buffer = MemoryBuffer.wrap(row.toBytes());
row.pointTo(buffer, 0, buffer.size());
final InterceptedType deserializedBean = encoder.fromRow(row);
Assert.assertEquals(deserializedBean.f1(), bean.f1() + 5);
@@ -300,7 +299,7 @@ public void testNestedCodecTypeInterception() {
final WrapInterceptedType bean = new WrapInterceptedTypeImpl(new InterceptedTypeImpl(42));
final RowEncoder encoder = Encoders.bean(WrapInterceptedType.class);
final BinaryRow row = encoder.toRow(bean);
- final MemoryBuffer buffer = MemoryUtils.wrap(row.toBytes());
+ final MemoryBuffer buffer = MemoryBuffer.wrap(row.toBytes());
row.pointTo(buffer, 0, buffer.size());
final WrapInterceptedType deserializedBean = encoder.fromRow(row);
Assert.assertEquals(deserializedBean.f1().f1(), bean.f1().f1() + 5);
diff --git a/java/fory-format/src/test/java/org/apache/fory/format/encoder/EnumTest.java b/java/fory-format/src/test/java/org/apache/fory/format/encoder/EnumTest.java
index 0677d67f86..88f4aed079 100644
--- a/java/fory-format/src/test/java/org/apache/fory/format/encoder/EnumTest.java
+++ b/java/fory-format/src/test/java/org/apache/fory/format/encoder/EnumTest.java
@@ -23,7 +23,6 @@
import lombok.Data;
import org.apache.fory.format.row.binary.BinaryRow;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.MemoryUtils;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -48,7 +47,7 @@ public void testEnumPresent() {
v.f2 = Optional.of(TestEnum.A);
RowEncoder encoder = Encoders.bean(EnumValue.class);
BinaryRow row = encoder.toRow(v);
- MemoryBuffer buffer = MemoryUtils.wrap(row.toBytes());
+ MemoryBuffer buffer = MemoryBuffer.wrap(row.toBytes());
row.pointTo(buffer, 0, buffer.size());
EnumValue deserializedV = encoder.fromRow(row);
Assert.assertEquals(v, deserializedV);
@@ -61,7 +60,7 @@ public void testEnumAbsent() {
v.f2 = Optional.empty();
RowEncoder encoder = Encoders.bean(EnumValue.class);
BinaryRow row = encoder.toRow(v);
- MemoryBuffer buffer = MemoryUtils.wrap(row.toBytes());
+ MemoryBuffer buffer = MemoryBuffer.wrap(row.toBytes());
row.pointTo(buffer, 0, buffer.size());
EnumValue deserializedV = encoder.fromRow(row);
Assert.assertEquals(v, deserializedV);
diff --git a/java/fory-format/src/test/java/org/apache/fory/format/encoder/GenericTypeTest.java b/java/fory-format/src/test/java/org/apache/fory/format/encoder/GenericTypeTest.java
index 6649d3d600..2551052e09 100644
--- a/java/fory-format/src/test/java/org/apache/fory/format/encoder/GenericTypeTest.java
+++ b/java/fory-format/src/test/java/org/apache/fory/format/encoder/GenericTypeTest.java
@@ -22,7 +22,6 @@
import lombok.Data;
import org.apache.fory.format.row.binary.BinaryRow;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.MemoryUtils;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -49,7 +48,7 @@ public void testRecursiveGenericType() {
bean.id.id = 42;
final RowEncoder encoder = Encoders.bean(TestEntity.class);
final BinaryRow row = encoder.toRow(bean);
- final MemoryBuffer buffer = MemoryUtils.wrap(row.toBytes());
+ final MemoryBuffer buffer = MemoryBuffer.wrap(row.toBytes());
row.pointTo(buffer, 0, buffer.size());
final TestEntity deserializedBean = encoder.fromRow(row);
Assert.assertEquals(deserializedBean, bean);
diff --git a/java/fory-format/src/test/java/org/apache/fory/format/encoder/ImplementInterfaceTest.java b/java/fory-format/src/test/java/org/apache/fory/format/encoder/ImplementInterfaceTest.java
index cdd38be6cf..4bc524814a 100644
--- a/java/fory-format/src/test/java/org/apache/fory/format/encoder/ImplementInterfaceTest.java
+++ b/java/fory-format/src/test/java/org/apache/fory/format/encoder/ImplementInterfaceTest.java
@@ -30,7 +30,6 @@
import org.apache.fory.format.row.binary.BinaryRow;
import org.apache.fory.format.type.DataTypes;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.MemoryUtils;
import org.apache.fory.reflect.TypeRef;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -91,7 +90,7 @@ public void testInterfaceTypes() {
final InterfaceType bean1 = new ImplementInterface(42, "42");
final RowEncoder encoder = Encoders.bean(InterfaceType.class);
final BinaryRow row = encoder.toRow(bean1);
- final MemoryBuffer buffer = MemoryUtils.wrap(row.toBytes());
+ final MemoryBuffer buffer = MemoryBuffer.wrap(row.toBytes());
row.pointTo(buffer, 0, buffer.size());
final InterfaceType deserializedBean = encoder.fromRow(row);
assertEquals(bean1, deserializedBean);
@@ -102,7 +101,7 @@ public void testNullValue() {
final InterfaceType bean1 = new ImplementInterface(42, null);
final RowEncoder encoder = Encoders.bean(InterfaceType.class);
final BinaryRow row = encoder.toRow(bean1);
- final MemoryBuffer buffer = MemoryUtils.wrap(row.toBytes());
+ final MemoryBuffer buffer = MemoryBuffer.wrap(row.toBytes());
row.pointTo(buffer, 0, buffer.size());
final InterfaceType deserializedBean = encoder.fromRow(row);
assertEquals(deserializedBean, bean1);
@@ -114,7 +113,7 @@ public void testNestedValue() {
bean1.nested = new ImplementNestedType("f3");
final RowEncoder encoder = Encoders.bean(InterfaceType.class);
final BinaryRow row = encoder.toRow(bean1);
- final MemoryBuffer buffer = MemoryUtils.wrap(row.toBytes());
+ final MemoryBuffer buffer = MemoryBuffer.wrap(row.toBytes());
row.pointTo(buffer, 0, buffer.size());
final InterfaceType deserializedBean = encoder.fromRow(row);
assertEquals(bean1, deserializedBean);
@@ -161,7 +160,7 @@ public void testNullOptional() {
final OptionalType bean1 = new OptionalTypeImpl(null);
final RowEncoder encoder = Encoders.bean(OptionalType.class);
final BinaryRow row = encoder.toRow(bean1);
- final MemoryBuffer buffer = MemoryUtils.wrap(row.toBytes());
+ final MemoryBuffer buffer = MemoryBuffer.wrap(row.toBytes());
row.pointTo(buffer, 0, buffer.size());
final OptionalType deserializedBean = encoder.fromRow(row);
Assert.assertEquals(deserializedBean.f1(), Optional.empty());
@@ -172,7 +171,7 @@ public void testPresentOptional() {
final OptionalType bean1 = new OptionalTypeImpl(Optional.of("42"));
final RowEncoder encoder = Encoders.bean(OptionalType.class);
final BinaryRow row = encoder.toRow(bean1);
- final MemoryBuffer buffer = MemoryUtils.wrap(row.toBytes());
+ final MemoryBuffer buffer = MemoryBuffer.wrap(row.toBytes());
row.pointTo(buffer, 0, buffer.size());
final OptionalType deserializedBean = encoder.fromRow(row);
Assert.assertEquals(deserializedBean.f1(), Optional.of("42"));
@@ -200,7 +199,7 @@ public Optional> f1() {
static class IdCodec implements CustomCodec.MemoryBufferCodec> {
@Override
public MemoryBuffer encode(final Id value) {
- return MemoryBuffer.fromByteArray(new byte[] {value.id});
+ return MemoryBuffer.wrap(new byte[] {value.id});
}
@Override
@@ -214,7 +213,7 @@ public void testOptionalCustomType() {
final OptionalCustomType bean1 = new OptionalCustomTypeImpl();
final RowEncoder encoder = Encoders.bean(OptionalCustomType.class);
final BinaryRow row = encoder.toRow(bean1);
- final MemoryBuffer buffer = MemoryUtils.wrap(row.toBytes());
+ final MemoryBuffer buffer = MemoryBuffer.wrap(row.toBytes());
row.pointTo(buffer, 0, buffer.size());
final OptionalCustomType deserializedBean = encoder.fromRow(row);
Assert.assertEquals(deserializedBean.f1().get().id, bean1.f1().get().id);
@@ -259,7 +258,7 @@ public void testListTooLazy() {
final ListOuter bean1 = new ListOuterImpl(Arrays.asList(new ListInnerImpl(42)));
final RowEncoder encoder = Encoders.bean(ListOuter.class);
final BinaryRow row = encoder.toRow(bean1);
- final MemoryBuffer buffer = MemoryUtils.wrap(row.toBytes());
+ final MemoryBuffer buffer = MemoryBuffer.wrap(row.toBytes());
row.pointTo(buffer, 0, buffer.size());
final ListOuter deserializedBean = encoder.fromRow(row);
Assert.assertEquals(deserializedBean.f1().get(0).f1(), 42);
@@ -370,7 +369,7 @@ public void testListElementsLazy() {
final RowEncoder encoder = Encoders.bean(ListLazyElemOuter.class);
final BinaryRow row = encoder.toRow(bean1);
ListLazyElemInner.check = true;
- final MemoryBuffer buffer = MemoryUtils.wrap(row.toBytes());
+ final MemoryBuffer buffer = MemoryBuffer.wrap(row.toBytes());
row.pointTo(buffer, 0, buffer.size());
final ListLazyElemOuter deserializedBean = encoder.fromRow(row);
Assert.assertEquals(deserializedBean.f1().get(2).f1(), 42);
diff --git a/java/fory-format/src/test/java/org/apache/fory/format/encoder/OptionalTest.java b/java/fory-format/src/test/java/org/apache/fory/format/encoder/OptionalTest.java
index 99e1f26327..b057fa90a5 100644
--- a/java/fory-format/src/test/java/org/apache/fory/format/encoder/OptionalTest.java
+++ b/java/fory-format/src/test/java/org/apache/fory/format/encoder/OptionalTest.java
@@ -26,7 +26,6 @@
import lombok.Data;
import org.apache.fory.format.row.binary.BinaryRow;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.MemoryUtils;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -47,7 +46,7 @@ public void testOptionalEmpty() {
bean.f2 = Optional.empty();
final RowEncoder encoder = Encoders.bean(OptionalType.class);
final BinaryRow row = encoder.toRow(bean);
- final MemoryBuffer buffer = MemoryUtils.wrap(row.toBytes());
+ final MemoryBuffer buffer = MemoryBuffer.wrap(row.toBytes());
row.pointTo(buffer, 0, buffer.size());
final OptionalType deserializedBean = encoder.fromRow(row);
Assert.assertEquals(deserializedBean, bean);
@@ -58,7 +57,7 @@ public void testOptionalNull() {
final OptionalType bean = new OptionalType();
final RowEncoder encoder = Encoders.bean(OptionalType.class);
final BinaryRow row = encoder.toRow(bean);
- final MemoryBuffer buffer = MemoryUtils.wrap(row.toBytes());
+ final MemoryBuffer buffer = MemoryBuffer.wrap(row.toBytes());
row.pointTo(buffer, 0, buffer.size());
final OptionalType deserializedBean = encoder.fromRow(row);
Assert.assertEquals(deserializedBean.f1, Optional.empty());
@@ -72,7 +71,7 @@ public void testOptionalPresent() {
bean.f2 = Optional.of("Indubitably");
final RowEncoder encoder = Encoders.bean(OptionalType.class);
final BinaryRow row = encoder.toRow(bean);
- final MemoryBuffer buffer = MemoryUtils.wrap(row.toBytes());
+ final MemoryBuffer buffer = MemoryBuffer.wrap(row.toBytes());
row.pointTo(buffer, 0, buffer.size());
final OptionalType deserializedBean = encoder.fromRow(row);
Assert.assertEquals(deserializedBean, bean);
@@ -91,7 +90,7 @@ public void testIntEmpty() {
bean.f1 = OptionalInt.empty();
final RowEncoder encoder = Encoders.bean(OptionalIntType.class);
final BinaryRow row = encoder.toRow(bean);
- final MemoryBuffer buffer = MemoryUtils.wrap(row.toBytes());
+ final MemoryBuffer buffer = MemoryBuffer.wrap(row.toBytes());
row.pointTo(buffer, 0, buffer.size());
final OptionalIntType deserializedBean = encoder.fromRow(row);
Assert.assertEquals(deserializedBean, bean);
@@ -103,7 +102,7 @@ public void testIntPresent() {
bean.f1 = OptionalInt.of(42);
final RowEncoder encoder = Encoders.bean(OptionalIntType.class);
final BinaryRow row = encoder.toRow(bean);
- final MemoryBuffer buffer = MemoryUtils.wrap(row.toBytes());
+ final MemoryBuffer buffer = MemoryBuffer.wrap(row.toBytes());
row.pointTo(buffer, 0, buffer.size());
final OptionalIntType deserializedBean = encoder.fromRow(row);
Assert.assertEquals(deserializedBean, bean);
@@ -122,7 +121,7 @@ public void testLongEmpty() {
bean.f1 = OptionalLong.empty();
final RowEncoder encoder = Encoders.bean(OptionalLongType.class);
final BinaryRow row = encoder.toRow(bean);
- final MemoryBuffer buffer = MemoryUtils.wrap(row.toBytes());
+ final MemoryBuffer buffer = MemoryBuffer.wrap(row.toBytes());
row.pointTo(buffer, 0, buffer.size());
final OptionalLongType deserializedBean = encoder.fromRow(row);
Assert.assertEquals(deserializedBean, bean);
@@ -134,7 +133,7 @@ public void testLongPresent() {
bean.f1 = OptionalLong.of(42);
final RowEncoder encoder = Encoders.bean(OptionalLongType.class);
final BinaryRow row = encoder.toRow(bean);
- final MemoryBuffer buffer = MemoryUtils.wrap(row.toBytes());
+ final MemoryBuffer buffer = MemoryBuffer.wrap(row.toBytes());
row.pointTo(buffer, 0, buffer.size());
final OptionalLongType deserializedBean = encoder.fromRow(row);
Assert.assertEquals(deserializedBean, bean);
@@ -153,7 +152,7 @@ public void testDoubleEmpty() {
bean.f1 = OptionalDouble.empty();
final RowEncoder encoder = Encoders.bean(OptionalDoubleType.class);
final BinaryRow row = encoder.toRow(bean);
- final MemoryBuffer buffer = MemoryUtils.wrap(row.toBytes());
+ final MemoryBuffer buffer = MemoryBuffer.wrap(row.toBytes());
row.pointTo(buffer, 0, buffer.size());
final OptionalDoubleType deserializedBean = encoder.fromRow(row);
Assert.assertEquals(deserializedBean, bean);
@@ -165,7 +164,7 @@ public void testDoublePresent() {
bean.f1 = OptionalDouble.of(42);
final RowEncoder encoder = Encoders.bean(OptionalDoubleType.class);
final BinaryRow row = encoder.toRow(bean);
- final MemoryBuffer buffer = MemoryUtils.wrap(row.toBytes());
+ final MemoryBuffer buffer = MemoryBuffer.wrap(row.toBytes());
row.pointTo(buffer, 0, buffer.size());
final OptionalDoubleType deserializedBean = encoder.fromRow(row);
Assert.assertEquals(deserializedBean, bean);
diff --git a/java/fory-format/src/test/java/org/apache/fory/format/encoder/RowEncoderTest.java b/java/fory-format/src/test/java/org/apache/fory/format/encoder/RowEncoderTest.java
index dd6832e9a6..17d16a6c28 100644
--- a/java/fory-format/src/test/java/org/apache/fory/format/encoder/RowEncoderTest.java
+++ b/java/fory-format/src/test/java/org/apache/fory/format/encoder/RowEncoderTest.java
@@ -30,7 +30,6 @@
import lombok.Data;
import org.apache.fory.format.row.binary.BinaryRow;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.MemoryUtils;
import org.apache.fory.test.bean.BeanA;
import org.apache.fory.test.bean.BeanB;
import org.testng.Assert;
@@ -96,7 +95,7 @@ public void testImportInnerClass() {
Foo foo = new Foo();
RowEncoder encoder = Encoders.bean(Foo.class);
BinaryRow row = encoder.toRow(foo);
- MemoryBuffer buffer = MemoryUtils.wrap(row.toBytes());
+ MemoryBuffer buffer = MemoryBuffer.wrap(row.toBytes());
row.pointTo(buffer, 0, buffer.size());
Foo deserializedFoo = encoder.fromRow(row);
Assert.assertEquals(foo, deserializedFoo);
diff --git a/java/fory-format/src/test/java/org/apache/fory/format/row/binary/BinaryMapTest.java b/java/fory-format/src/test/java/org/apache/fory/format/row/binary/BinaryMapTest.java
index b11a03bc5f..6f6958551f 100644
--- a/java/fory-format/src/test/java/org/apache/fory/format/row/binary/BinaryMapTest.java
+++ b/java/fory-format/src/test/java/org/apache/fory/format/row/binary/BinaryMapTest.java
@@ -27,14 +27,13 @@
import org.apache.fory.format.row.binary.writer.BinaryRowWriter;
import org.apache.fory.format.type.DataTypes;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.MemoryUtils;
import org.testng.annotations.Test;
public class BinaryMapTest {
@Test
public void pointTo() {
- MemoryBuffer buffer = MemoryUtils.buffer(1024);
+ MemoryBuffer buffer = MemoryBuffer.buffer(1024);
int writerIndex = 8; // preserve 8 byte for numBytes
BinaryArrayWriter keyArrayWriter =
new BinaryArrayWriter(DataTypes.arrayField(DataTypes.utf8()));
diff --git a/java/fory-format/src/test/java/org/apache/fory/format/row/binary/BinaryRowTest.java b/java/fory-format/src/test/java/org/apache/fory/format/row/binary/BinaryRowTest.java
index a40139ddfd..0203939993 100644
--- a/java/fory-format/src/test/java/org/apache/fory/format/row/binary/BinaryRowTest.java
+++ b/java/fory-format/src/test/java/org/apache/fory/format/row/binary/BinaryRowTest.java
@@ -30,7 +30,6 @@
import org.apache.fory.logging.Logger;
import org.apache.fory.logging.LoggerFactory;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.MemoryUtils;
import org.apache.fory.memory.Platform;
import org.testng.annotations.Test;
@@ -40,7 +39,7 @@ public class BinaryRowTest {
// test align to see whether align can bring us performance gains.
@Test(enabled = false)
public void testAlign() {
- MemoryBuffer buf = MemoryUtils.buffer(64);
+ MemoryBuffer buf = MemoryBuffer.buffer(64);
buf.putInt64(6, 100L);
buf.putInt64(14, 100L);
long nums = 1000_000_000;
@@ -57,7 +56,7 @@ public void testAlign() {
long duration = System.nanoTime() - t;
System.out.format("non-aligned cost:\ttotal %sns %sms\n", duration, duration / 1000_000);
- MemoryBuffer buf2 = MemoryUtils.buffer(64);
+ MemoryBuffer buf2 = MemoryBuffer.buffer(64);
buf2.putInt64(8, 100L);
buf2.putInt64(16, 100L);
// warm
diff --git a/java/fory-format/src/test/java/org/apache/fory/format/vectorized/ArrowSerializersTest.java b/java/fory-format/src/test/java/org/apache/fory/format/vectorized/ArrowSerializersTest.java
index 5300ef1c8c..c3770919ef 100644
--- a/java/fory-format/src/test/java/org/apache/fory/format/vectorized/ArrowSerializersTest.java
+++ b/java/fory-format/src/test/java/org/apache/fory/format/vectorized/ArrowSerializersTest.java
@@ -39,7 +39,6 @@
import org.apache.fory.io.MemoryBufferReadableChannel;
import org.apache.fory.io.MemoryBufferWritableChannel;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.MemoryUtils;
import org.apache.fory.resolver.ClassResolver;
import org.apache.fory.serializer.BufferObject;
import org.testng.Assert;
@@ -96,7 +95,7 @@ public void testWriteVectorSchemaRoot() throws IOException {
bufferObjects.stream().map(BufferObject::toBuffer).collect(Collectors.toList());
MemoryBuffer buffer = buffers.get(0);
- MemoryBuffer buffer2 = MemoryUtils.buffer(32);
+ MemoryBuffer buffer2 = MemoryBuffer.buffer(32);
try (ArrowStreamWriter writer =
new ArrowStreamWriter(root, null, new MemoryBufferWritableChannel(buffer2))) {
// this will make root empty.
diff --git a/java/fory-format/src/test/java/org/apache/fory/format/vectorized/ArrowUtilsTest.java b/java/fory-format/src/test/java/org/apache/fory/format/vectorized/ArrowUtilsTest.java
index 48a00cc5aa..ced9cbb150 100644
--- a/java/fory-format/src/test/java/org/apache/fory/format/vectorized/ArrowUtilsTest.java
+++ b/java/fory-format/src/test/java/org/apache/fory/format/vectorized/ArrowUtilsTest.java
@@ -32,7 +32,6 @@
import org.apache.arrow.vector.ipc.message.ArrowRecordBatch;
import org.apache.arrow.vector.types.pojo.Field;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.MemoryUtils;
import org.testng.annotations.Test;
public class ArrowUtilsTest {
@@ -56,7 +55,7 @@ public void testSerializeRecordBatch() {
VectorSchemaRoot vectorSchemaRoot = createVectorSchemaRoot(2);
VectorUnloader unloader = new VectorUnloader(vectorSchemaRoot);
ArrowRecordBatch recordBatch = unloader.getRecordBatch();
- MemoryBuffer buffer = MemoryUtils.buffer(32);
+ MemoryBuffer buffer = MemoryBuffer.buffer(32);
ArrowUtils.serializeRecordBatch(recordBatch, buffer);
try (ArrowRecordBatch batch = ArrowUtils.deserializeRecordBatch(buffer)) {
System.out.println("newRecordBatch " + batch);
diff --git a/java/fory-format/src/test/java/org/apache/fory/format/vectorized/ArrowWriterTest.java b/java/fory-format/src/test/java/org/apache/fory/format/vectorized/ArrowWriterTest.java
index 2951a91ea9..80da14ff79 100644
--- a/java/fory-format/src/test/java/org/apache/fory/format/vectorized/ArrowWriterTest.java
+++ b/java/fory-format/src/test/java/org/apache/fory/format/vectorized/ArrowWriterTest.java
@@ -26,7 +26,6 @@
import org.apache.fory.format.row.binary.BinaryRow;
import org.apache.fory.format.type.TypeInference;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.MemoryUtils;
import org.apache.fory.test.bean.BeanA;
import org.testng.annotations.Test;
@@ -69,7 +68,7 @@ public void testWrite() {
public void testSerializeArrowRecordBatch() {
ArrowRecordBatch recordBatch = createArrowRecordBatch();
System.out.println("recordBatch serialized body size " + recordBatch.computeBodyLength());
- MemoryBuffer buffer = MemoryUtils.buffer(32);
+ MemoryBuffer buffer = MemoryBuffer.buffer(32);
ArrowUtils.serializeRecordBatch(recordBatch, buffer);
System.out.println("IPC recordBatch size " + buffer.writerIndex());
ArrowRecordBatch newRecordBatch = ArrowUtils.deserializeRecordBatch(buffer);
diff --git a/java/fory-testsuite/src/test/java/org/apache/fory/benchmark/SerializationBenchmark.java b/java/fory-testsuite/src/test/java/org/apache/fory/benchmark/SerializationBenchmark.java
index 2d48822580..f8765f74fd 100644
--- a/java/fory-testsuite/src/test/java/org/apache/fory/benchmark/SerializationBenchmark.java
+++ b/java/fory-testsuite/src/test/java/org/apache/fory/benchmark/SerializationBenchmark.java
@@ -31,7 +31,6 @@
import org.apache.fory.logging.Logger;
import org.apache.fory.logging.LoggerFactory;
import org.apache.fory.memory.MemoryBuffer;
-import org.apache.fory.memory.MemoryUtils;
import org.apache.fory.test.bean.Foo;
import org.nustaq.serialization.FSTConfiguration;
import org.testng.annotations.BeforeTest;
@@ -104,7 +103,7 @@ private void testFory(Object obj) {
.requireClassRegistration(false)
.build();
fory.register(obj.getClass());
- MemoryBuffer buffer = MemoryUtils.buffer(32);
+ MemoryBuffer buffer = MemoryBuffer.buffer(32);
// warm
for (int i = 0; i < iterNums; i++) {
buffer.writerIndex(0);