This is an automated email from the ASF dual-hosted git repository.
chaokunyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory.git
The following commit(s) were added to refs/heads/main by this push:
new 297c34506 feat(java): add java9/16 module-info support (#3721)
297c34506 is described below
commit 297c34506ab7c6f57dee875f090002a38ce7478e
Author: Shawn Yang <[email protected]>
AuthorDate: Sun May 31 02:43:48 2026 +0800
feat(java): add java9/16 module-info support (#3721)
## Why?
## What does this PR do?
## Related issues
## AI Contribution Checklist
- [ ] Substantial AI assistance was used in this PR: `yes` / `no`
- [ ] If `yes`, I included a completed [AI Contribution
Checklist](https://github.com/apache/fory/blob/main/AI_POLICY.md#9-contributor-checklist-for-ai-assisted-prs)
in this PR description and the required `AI Usage Disclosure`.
- [ ] If `yes`, my PR description includes the required `ai_review`
summary and screenshot evidence of the final clean AI review results
from both fresh reviewers on the current PR diff or current HEAD after
the latest code changes.
## Does this PR introduce any user-facing change?
- [ ] Does this PR introduce any public API change?
- [ ] Does this PR introduce any binary protocol compatibility change?
## Benchmark
---
ci/run_ci.sh | 1 +
integration_tests/jpms_tests/run_jlink_smoke.sh | 200 +++++++++++++++++++++
java/fory-core/pom.xml | 191 ++++++++++++++++++++
java/fory-core/src/main/java16/module-info.java | 59 ++++++
.../serializer/CompressedArraySerializers.java | 2 +-
.../apache/fory/util/ArrayCompressionUtils.java | 129 ++++++-------
.../fory/util/PrimitiveArrayCompressionType.java | 22 ++-
java/fory-core/src/main/java9/module-info.java | 58 ++++++
java/fory-format/pom.xml | 68 +++++++
.../apache/fory/format/encoder/LazyArrayData.java | 2 +-
java/fory-format/src/main/java11/module-info.java | 33 ++++
java/fory-simd/pom.xml | 94 ----------
java/fory-testsuite/pom.xml | 59 ++++++
.../fory/serializer/ArrayCompressionTest.java | 1 -
.../fory/serializer/ArrayCompressionUtilsTest.java | 1 -
java/pom.xml | 1 -
16 files changed, 739 insertions(+), 182 deletions(-)
diff --git a/ci/run_ci.sh b/ci/run_ci.sh
index 45e096a45..fafe3185d 100755
--- a/ci/run_ci.sh
+++ b/ci/run_ci.sh
@@ -98,6 +98,7 @@ integration_tests() {
echo "Start JPMS tests"
cd "$ROOT"/integration_tests/jpms_tests
mvn -T10 -B --no-transfer-progress clean compile
+ ./run_jlink_smoke.sh
echo "Start jdk compatibility tests"
cd "$ROOT"/integration_tests/jdk_compatibility_tests
mvn -T10 -B --no-transfer-progress clean test
diff --git a/integration_tests/jpms_tests/run_jlink_smoke.sh
b/integration_tests/jpms_tests/run_jlink_smoke.sh
new file mode 100755
index 000000000..08364dc48
--- /dev/null
+++ b/integration_tests/jpms_tests/run_jlink_smoke.sh
@@ -0,0 +1,200 @@
+#!/usr/bin/env bash
+
+# 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.
+
+set -euo pipefail
+
+ROOT="$(git rev-parse --show-toplevel)"
+JAVA_ROOT="$ROOT/java"
+VERSION="$(mvn -q -B -f "$JAVA_ROOT/pom.xml" help:evaluate
-Dexpression=project.version -DforceStdout)"
+JAVA_HOME="${JAVA_HOME:-$(
+ java -XshowSettings:properties -version 2>&1 \
+ | awk -F= '/java.home =/ { gsub(/^ +| +$/, "", $2); print $2; exit }'
+)}"
+JAVA_MAJOR="$(
+ java -version 2>&1 \
+ | awk -F '"' '/version/ {print $2; exit}' \
+ | awk -F. '{ if ($1 == "1") print $2; else print $1 }'
+)"
+
+if [[ "$JAVA_MAJOR" -lt 11 ]]; then
+ echo "Skipping jlink smoke test on JDK $JAVA_MAJOR; fory-format is Java 11+."
+ exit 0
+fi
+if [[ ! -d "$JAVA_HOME/jmods" ]]; then
+ echo "Cannot find JDK modules under JAVA_HOME=$JAVA_HOME; jlink smoke
requires a JDK." >&2
+ exit 1
+fi
+
+artifact_jar() {
+ local artifact="$1"
+ local module="$2"
+ local target_jar="$JAVA_ROOT/$module/target/$artifact-$VERSION.jar"
+ local
repo_jar="$HOME/.m2/repository/org/apache/fory/$artifact/$VERSION/$artifact-$VERSION.jar"
+ if [[ -f "$target_jar" ]]; then
+ echo "$target_jar"
+ elif [[ -f "$repo_jar" ]]; then
+ echo "$repo_jar"
+ else
+ echo "Cannot find $artifact jar; run java/fory-core and java/fory-format
package/install first." >&2
+ exit 1
+ fi
+}
+
+CORE_JAR="$(artifact_jar fory-core fory-core)"
+FORMAT_JAR="$(artifact_jar fory-format fory-format)"
+WORK_DIR="$(mktemp -d "${TMPDIR:-/tmp}/fory-jpms-jlink.XXXXXX")"
+trap 'rm -rf "$WORK_DIR"' EXIT
+
+require_jar_entry() {
+ local jar_file="$1"
+ local entry="$2"
+ if ! jar tf "$jar_file" | grep -qx "$entry"; then
+ echo "Missing $entry in $jar_file" >&2
+ exit 1
+ fi
+}
+
+reject_jar_entry() {
+ local jar_file="$1"
+ local entry="$2"
+ if jar tf "$jar_file" | grep -qx "$entry"; then
+ echo "Unexpected root $entry in $jar_file" >&2
+ exit 1
+ fi
+}
+
+require_jar_entry "$CORE_JAR" "META-INF/versions/9/module-info.class"
+reject_jar_entry "$CORE_JAR" "module-info.class"
+require_jar_entry "$FORMAT_JAR" "META-INF/versions/11/module-info.class"
+reject_jar_entry "$FORMAT_JAR" "module-info.class"
+
+if [[ "$JAVA_MAJOR" -ge 16 ]] \
+ && jar tf "$CORE_JAR" | grep -qx "META-INF/versions/16/module-info.class";
then
+ require_jar_entry "$CORE_JAR"
"META-INF/versions/16/org/apache/fory/serializer/CompressedArraySerializers.class"
+ require_jar_entry "$CORE_JAR"
"META-INF/versions/16/org/apache/fory/util/ArrayCompressionUtils.class"
+ require_jar_entry "$CORE_JAR"
"META-INF/versions/16/org/apache/fory/util/PrimitiveArrayCompressionType.class"
+ reject_jar_entry "$CORE_JAR"
"org/apache/fory/serializer/CompressedArraySerializers.class"
+ reject_jar_entry "$CORE_JAR"
"org/apache/fory/util/ArrayCompressionUtils.class"
+ reject_jar_entry "$CORE_JAR"
"org/apache/fory/util/PrimitiveArrayCompressionType.class"
+ jar --file "$CORE_JAR" --describe-module --release 16 | grep -q "requires
jdk.incubator.vector static"
+fi
+
+jar --file "$CORE_JAR" --describe-module --release 9 | grep -q "requires
java.sql static"
+jar --file "$CORE_JAR" --describe-module --release 9 | grep -q "requires
com.google.common static"
+jar --file "$FORMAT_JAR" --describe-module --release 11 | grep -q "requires
java.sql static"
+jar --file "$FORMAT_JAR" --describe-module --release 11 | grep -q "requires
org.apache.arrow.vector static transitive"
+jar --file "$FORMAT_JAR" --describe-module --release 11 | grep -q "requires
org.apache.arrow.memory.core static transitive"
+
+DEPS_FILE="$WORK_DIR/format-deps.txt"
+mvn -q -B -f "$JAVA_ROOT/pom.xml" -pl fory-format dependency:list \
+ -DincludeScope=compile \
+ -DoutputAbsoluteArtifactFilename=true \
+ -DexcludeTransitive=false \
+ -DoutputFile="$DEPS_FILE" \
+ -Dstyle.color=never
+
+COMPILE_MODULE_PATH="$WORK_DIR/compile-module-path.txt"
+awk -F: '/:jar:/ {
+ path = $NF
+ sub(/ .*/, "", path)
+ if (path ~ /^\// && path ~ /\.jar$/ && path !~
/\/org\/apache\/fory\/fory-core\//) {
+ print path
+ }
+}' "$DEPS_FILE" > "$COMPILE_MODULE_PATH"
+
+mkdir -p "$WORK_DIR/src/jpms.smoke/org/apache/fory/jpms" "$WORK_DIR/mods"
+cat > "$WORK_DIR/src/jpms.smoke/module-info.java" <<'EOF'
+module jpms.smoke {
+ requires org.apache.fory.core;
+ requires org.apache.fory.format;
+}
+EOF
+cat > "$WORK_DIR/src/jpms.smoke/org/apache/fory/jpms/Smoke.java" <<'EOF'
+package org.apache.fory.jpms;
+
+import org.apache.fory.Fory;
+
+public final class Smoke {
+ public static void main(String[] args) throws Exception {
+ Fory.builder().build();
+ Class.forName("org.apache.fory.format.encoder.Encoders");
+ System.out.println("ok");
+ }
+}
+EOF
+
+JOINED_COMPILE_MODULE_PATH="$CORE_JAR:$FORMAT_JAR"
+if [[ -s "$COMPILE_MODULE_PATH" ]]; then
+ JOINED_COMPILE_MODULE_PATH="$JOINED_COMPILE_MODULE_PATH:$(paste -sd:
"$COMPILE_MODULE_PATH")"
+fi
+
+javac \
+ --module-path "$JOINED_COMPILE_MODULE_PATH" \
+ -d "$WORK_DIR/mods" \
+ --module-source-path "$WORK_DIR/src" \
+ -m jpms.smoke
+
+jlink \
+ --module-path "$JAVA_HOME/jmods:$CORE_JAR:$FORMAT_JAR:$WORK_DIR/mods" \
+ --add-modules jpms.smoke \
+ --output "$WORK_DIR/image"
+
+"$WORK_DIR/image/bin/java" -m jpms.smoke/org.apache.fory.jpms.Smoke | grep -qx
"ok"
+
+IMAGE_MODULES="$("$WORK_DIR/image/bin/java" --list-modules)"
+echo "$IMAGE_MODULES" | grep -q "^org.apache.fory.core"
+echo "$IMAGE_MODULES" | grep -q "^org.apache.fory.format"
+if echo "$IMAGE_MODULES" \
+ | grep -Eq
"^(java\.sql|com\.google|jsr305|org\.apache\.arrow|org\.slf4j|jdk\.incubator\.vector)";
then
+ echo "Optional static modules leaked into the minimal jlink image:" >&2
+ echo "$IMAGE_MODULES" \
+ | grep -E
"^(java\.sql|com\.google|jsr305|org\.apache\.arrow|org\.slf4j|jdk\.incubator\.vector)"
>&2
+ exit 1
+fi
+
+if [[ "$JAVA_MAJOR" -ge 16 ]] \
+ && jar tf "$CORE_JAR" | grep -qx
"META-INF/versions/16/org/apache/fory/util/ArrayCompressionUtils.class"; then
+ mkdir -p "$WORK_DIR/vector-classes"
+ cat > "$WORK_DIR/VectorSmoke.java" <<'EOF'
+import org.apache.fory.util.ArrayCompressionUtils;
+import org.apache.fory.util.PrimitiveArrayCompressionType;
+
+public final class VectorSmoke {
+ public static void main(String[] args) throws Exception {
+ int[] values = new int[1024];
+ for (int i = 0; i < values.length; i++) {
+ values[i] = (i & 0xff) - 128;
+ }
+ if (ArrayCompressionUtils.determineIntCompressionType(values)
+ != PrimitiveArrayCompressionType.INT_TO_BYTE) {
+ throw new AssertionError("Vector compression returned the wrong range");
+ }
+ System.out.println("vector-ok");
+ }
+}
+EOF
+ javac -cp "$CORE_JAR" -d "$WORK_DIR/vector-classes"
"$WORK_DIR/VectorSmoke.java"
+ java \
+ --add-modules jdk.incubator.vector \
+ -cp "$CORE_JAR:$WORK_DIR/vector-classes" \
+ VectorSmoke \
+ | grep -qx "vector-ok"
+fi
+
+echo "JPMS jlink smoke test passed with minimal optional dependencies."
diff --git a/java/fory-core/pom.xml b/java/fory-core/pom.xml
index 4176d7418..23d05bd6a 100644
--- a/java/fory-core/pom.xml
+++ b/java/fory-core/pom.xml
@@ -78,6 +78,7 @@
<archive>
<manifestEntries>
<Automatic-Module-Name>org.apache.fory.core</Automatic-Module-Name>
+ <Multi-Release>true</Multi-Release>
</manifestEntries>
</archive>
</configuration>
@@ -119,6 +120,7 @@
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<manifestEntries>
<Automatic-Module-Name>org.apache.fory.core</Automatic-Module-Name>
+ <Multi-Release>true</Multi-Release>
</manifestEntries>
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
@@ -135,6 +137,195 @@
</build>
<profiles>
+ <profile>
+ <id>jpms-java9</id>
+ <activation>
+ <jdk>[9,)</jdk>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <version>3.1.0</version>
+ <executions>
+ <execution>
+ <id>compile-java9-module-info</id>
+ <phase>process-classes</phase>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ <configuration>
+ <target>
+ <mkdir
dir="${project.build.directory}/jpms-classes/java9"/>
+ <pathconvert property="compile.module.path"
refid="maven.compile.classpath"
+ pathsep="${path.separator}"/>
+ <javac srcdir="${project.basedir}/src/main/java9"
+
destdir="${project.build.directory}/jpms-classes/java9"
+ includeantruntime="false"
+ fork="true"
+ executable="${java.home}/bin/javac"
+ debug="true">
+ <include name="module-info.java"/>
+ <compilerarg value="--release"/>
+ <compilerarg value="9"/>
+ <compilerarg value="--module-path"/>
+ <compilerarg path="${compile.module.path}"/>
+ <compilerarg value="--patch-module"/>
+ <compilerarg
value="org.apache.fory.core=${project.build.outputDirectory}"/>
+ </javac>
+ </target>
+ </configuration>
+ </execution>
+ <execution>
+ <id>inject-java9-module-info</id>
+ <phase>package</phase>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ <configuration>
+ <target>
+ <jar
destfile="${project.build.directory}/${project.build.finalName}.jar"
update="true">
+ <zipfileset
dir="${project.build.outputDirectory}/META-INF/versions/9"
+ prefix="META-INF/versions/9"
+ includes="module-info.class"/>
+ </jar>
+ </target>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>3.3.1</version>
+ <executions>
+ <execution>
+ <id>copy-java9-module-info</id>
+ <phase>prepare-package</phase>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals>
+ <configuration>
+
<outputDirectory>${project.build.outputDirectory}/META-INF/versions/9</outputDirectory>
+ <resources>
+ <resource>
+
<directory>${project.build.directory}/jpms-classes/java9</directory>
+ <includes>
+ <include>module-info.class</include>
+ </includes>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>jpms-java16</id>
+ <activation>
+ <jdk>[16,)</jdk>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <version>3.1.0</version>
+ <executions>
+ <execution>
+ <id>compile-java16-sources</id>
+ <phase>process-classes</phase>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ <configuration>
+ <target>
+ <delete
dir="${project.build.directory}/jpms-classes/java16"/>
+ <mkdir
dir="${project.build.directory}/jpms-classes/java16"/>
+ <pathconvert property="compile.module.path"
refid="maven.compile.classpath"
+ pathsep="${path.separator}"/>
+ <javac srcdir="${project.basedir}/src/main/java16"
+
destdir="${project.build.directory}/jpms-classes/java16"
+ includeantruntime="false"
+ fork="true"
+ executable="${java.home}/bin/javac"
+ debug="true">
+ <include name="**/*.java"/>
+ <compilerarg value="--source"/>
+ <compilerarg value="16"/>
+ <compilerarg value="--target"/>
+ <compilerarg value="16"/>
+ <compilerarg value="--module-path"/>
+ <compilerarg path="${compile.module.path}"/>
+ <compilerarg value="--add-modules"/>
+ <compilerarg value="jdk.incubator.vector"/>
+ <compilerarg value="--patch-module"/>
+ <compilerarg
value="org.apache.fory.core=${project.build.outputDirectory}"/>
+ </javac>
+ </target>
+ </configuration>
+ </execution>
+ <execution>
+ <id>clean-java16-package-classes</id>
+ <phase>prepare-package</phase>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ <configuration>
+ <target>
+ <delete
dir="${project.build.outputDirectory}/META-INF/versions/16"/>
+ </target>
+ </configuration>
+ </execution>
+ <execution>
+ <id>inject-java16-classes</id>
+ <phase>package</phase>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ <configuration>
+ <target>
+ <jar
destfile="${project.build.directory}/${project.build.finalName}.jar"
update="true">
+ <zipfileset
dir="${project.build.outputDirectory}/META-INF/versions/16"
+ prefix="META-INF/versions/16"
+ includes="**/*.class"/>
+ </jar>
+ </target>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>3.3.1</version>
+ <executions>
+ <execution>
+ <id>copy-java16-classes</id>
+ <phase>prepare-package</phase>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals>
+ <configuration>
+
<outputDirectory>${project.build.outputDirectory}/META-INF/versions/16</outputDirectory>
+ <resources>
+ <resource>
+
<directory>${project.build.directory}/jpms-classes/java16</directory>
+ <includes>
+ <include>**/*.class</include>
+ </includes>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
<profile>
<id>xlang-parallel</id>
<activation>
diff --git a/java/fory-core/src/main/java16/module-info.java
b/java/fory-core/src/main/java16/module-info.java
new file mode 100644
index 000000000..40c773b6a
--- /dev/null
+++ b/java/fory-core/src/main/java16/module-info.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+module org.apache.fory.core {
+ requires java.logging;
+ requires jdk.unsupported;
+
+ requires static java.sql;
+ requires static com.google.common;
+ requires static org.slf4j;
+ requires static jsr305;
+ requires static jdk.incubator.vector;
+
+ exports org.apache.fory;
+ exports org.apache.fory.annotation;
+ exports org.apache.fory.builder;
+ exports org.apache.fory.codegen;
+ exports org.apache.fory.collection;
+ exports org.apache.fory.config;
+ exports org.apache.fory.context;
+ exports org.apache.fory.exception;
+ exports org.apache.fory.io;
+ exports org.apache.fory.logging;
+ exports org.apache.fory.memory;
+ exports org.apache.fory.meta;
+ exports org.apache.fory.platform;
+ exports org.apache.fory.pool;
+ exports org.apache.fory.reflect;
+ exports org.apache.fory.resolver;
+ exports org.apache.fory.serializer;
+ exports org.apache.fory.serializer.collection;
+ exports org.apache.fory.serializer.converter;
+ exports org.apache.fory.serializer.scala;
+ exports org.apache.fory.serializer.struct;
+ exports org.apache.fory.type;
+ exports org.apache.fory.type.union;
+ exports org.apache.fory.type.unsigned;
+ exports org.apache.fory.util;
+ exports org.apache.fory.util.function;
+ exports org.apache.fory.util.record;
+ exports org.apache.fory.util.unsafe to
+ org.apache.fory.format;
+}
diff --git
a/java/fory-simd/src/main/java/org/apache/fory/serializer/CompressedArraySerializers.java
b/java/fory-core/src/main/java16/org/apache/fory/serializer/CompressedArraySerializers.java
similarity index 99%
rename from
java/fory-simd/src/main/java/org/apache/fory/serializer/CompressedArraySerializers.java
rename to
java/fory-core/src/main/java16/org/apache/fory/serializer/CompressedArraySerializers.java
index ba4f2e247..9f4eee99c 100644
---
a/java/fory-simd/src/main/java/org/apache/fory/serializer/CompressedArraySerializers.java
+++
b/java/fory-core/src/main/java16/org/apache/fory/serializer/CompressedArraySerializers.java
@@ -36,7 +36,7 @@ import org.apache.fory.util.ArrayCompressionUtils;
import org.apache.fory.util.PrimitiveArrayCompressionType;
/**
- * Compressed array serializers using Java 16+ Vector API for SIMD
acceleration.
+ * Compressed array serializers with optional Java 16+ Vector API acceleration.
*
* <p>To use these serializers, simply call {@code
CompressedArraySerializers.register(fory)} on
* your Fory instance. These will override the default array serializers for
{@code int[]} and
diff --git
a/java/fory-simd/src/main/java/org/apache/fory/util/ArrayCompressionUtils.java
b/java/fory-core/src/main/java16/org/apache/fory/util/ArrayCompressionUtils.java
similarity index 60%
rename from
java/fory-simd/src/main/java/org/apache/fory/util/ArrayCompressionUtils.java
rename to
java/fory-core/src/main/java16/org/apache/fory/util/ArrayCompressionUtils.java
index a55a53da8..08d2111df 100644
---
a/java/fory-simd/src/main/java/org/apache/fory/util/ArrayCompressionUtils.java
+++
b/java/fory-core/src/main/java16/org/apache/fory/util/ArrayCompressionUtils.java
@@ -25,75 +25,64 @@ import jdk.incubator.vector.VectorOperators;
import jdk.incubator.vector.VectorSpecies;
/**
- * Utility class for primitive array compression operations. It uses
SIMD-accelerated array
- * compression using Java 16+ Vector API.
+ * Utility methods for optional primitive array compression.
*
- * <p>This utility provides compression for primitive arrays by detecting when
values can fit in
- * smaller data types:
+ * <p>The compressed array serializers use these helpers when every value in a
primitive array fits
+ * in a narrower primitive type:
*
* <ul>
- * <li>int[] → byte[] when all values are in [-128, 127] range (75% size
reduction)
- * <li>int[] → short[] when all values are in [-32768, 32767] range (50%
size reduction)
- * <li>long[] → int[] when all values fit in integer range (50% size
reduction)
+ * <li>{@code int[]} to {@code byte[]} when all values are in byte range.
+ * <li>{@code int[]} to {@code short[]} when all values are in short range.
+ * <li>{@code long[]} to {@code int[]} when all values are in int range.
* </ul>
- *
- * <p>Uses the best available compression provider via ServiceLoader pattern.
SIMD optimizations are
- * used when fory-simd module is available. When no compression provider is
available, compression
- * is disabled entirely.
*/
public final class ArrayCompressionUtils {
+ // Minimum array size to justify compression analysis and the compressed
payload marker overhead.
+ static final int MIN_COMPRESSION_SIZE = 1 << 9;
private static final VectorSpecies<Integer> INT_SPECIES =
IntVector.SPECIES_PREFERRED;
private static final VectorSpecies<Long> LONG_SPECIES =
LongVector.SPECIES_PREFERRED;
- // Minimum array size to justify compression overhead
- private static final int MIN_COMPRESSION_SIZE = 1 << 9; // 512 elements
+ private ArrayCompressionUtils() {}
/**
- * Determine the best compression type for int array.
+ * Determines the best compression type for an int array.
*
- * @param array the int array to analyze
- * @return compression type (NONE, INT_TO_BYTE, or INT_TO_SHORT)
- * @throws NullPointerException if array is null
+ * @param array the array to analyze
+ * @return {@link PrimitiveArrayCompressionType#INT_TO_BYTE}, {@link
+ * PrimitiveArrayCompressionType#INT_TO_SHORT}, or {@link
PrimitiveArrayCompressionType#NONE}
+ * @throws NullPointerException if {@code array} is null
*/
public static PrimitiveArrayCompressionType
determineIntCompressionType(int[] array) {
if (array == null) {
throw new NullPointerException("Input array cannot be null");
}
if (array.length < MIN_COMPRESSION_SIZE) {
- // No compression for empty or too small arrays
return PrimitiveArrayCompressionType.NONE;
}
-
boolean canCompressToByte = true;
boolean canCompressToShort = true;
-
int i = 0;
- final int upperBound = INT_SPECIES.loopBound(array.length);
+ int upperBound = INT_SPECIES.loopBound(array.length);
- // SIMD loop
+ // Vector loop: test each lane against the target primitive ranges and
stop checking a narrower
+ // representation once any lane exceeds its range.
for (; i < upperBound && (canCompressToByte || canCompressToShort); i +=
INT_SPECIES.length()) {
IntVector vector = IntVector.fromArray(INT_SPECIES, array, i);
-
- // Check byte compression using mask operations
if (canCompressToByte) {
- var byteMaxMask = vector.compare(VectorOperators.GT, Byte.MAX_VALUE);
- var byteMinMask = vector.compare(VectorOperators.LT, Byte.MIN_VALUE);
- if (byteMaxMask.anyTrue() || byteMinMask.anyTrue()) {
+ if (vector.compare(VectorOperators.GT, Byte.MAX_VALUE).anyTrue()
+ || vector.compare(VectorOperators.LT, Byte.MIN_VALUE).anyTrue()) {
canCompressToByte = false;
}
}
-
- // Check short compression using mask operations
if (canCompressToShort) {
- var shortMaxMask = vector.compare(VectorOperators.GT, Short.MAX_VALUE);
- var shortMinMask = vector.compare(VectorOperators.LT, Short.MIN_VALUE);
- if (shortMaxMask.anyTrue() || shortMinMask.anyTrue()) {
+ if (vector.compare(VectorOperators.GT, Short.MAX_VALUE).anyTrue()
+ || vector.compare(VectorOperators.LT, Short.MIN_VALUE).anyTrue()) {
canCompressToShort = false;
}
}
}
- // Handle remaining elements with scalar code
+ // Scalar tail for elements that do not fill a complete vector.
for (; i < array.length && (canCompressToByte || canCompressToShort); i++)
{
int value = array[i];
if (canCompressToByte && (value < Byte.MIN_VALUE || value >
Byte.MAX_VALUE)) {
@@ -103,22 +92,21 @@ public final class ArrayCompressionUtils {
canCompressToShort = false;
}
}
-
if (canCompressToByte) {
return PrimitiveArrayCompressionType.INT_TO_BYTE;
- } else if (canCompressToShort) {
- return PrimitiveArrayCompressionType.INT_TO_SHORT;
- } else {
- return PrimitiveArrayCompressionType.NONE;
}
+ return canCompressToShort
+ ? PrimitiveArrayCompressionType.INT_TO_SHORT
+ : PrimitiveArrayCompressionType.NONE;
}
/**
- * Determine the best compression type for long array.
+ * Determines the best compression type for a long array.
*
- * @param array the long array to analyze
- * @return compression type (NONE or LONG_TO_INT)
- * @throws NullPointerException if array is null
+ * @param array the array to analyze
+ * @return {@link PrimitiveArrayCompressionType#LONG_TO_INT} or {@link
+ * PrimitiveArrayCompressionType#NONE}
+ * @throws NullPointerException if {@code array} is null
*/
public static PrimitiveArrayCompressionType
determineLongCompressionType(long[] array) {
if (array == null) {
@@ -127,42 +115,34 @@ public final class ArrayCompressionUtils {
if (array.length < MIN_COMPRESSION_SIZE) {
return PrimitiveArrayCompressionType.NONE;
}
- boolean canCompressToInt = true;
-
int i = 0;
int upperBound = LONG_SPECIES.loopBound(array.length);
- // SIMD loop
- for (; i < upperBound && canCompressToInt; i += LONG_SPECIES.length()) {
+ // Vector loop: any lane outside int range means long-to-int compression
is not safe.
+ for (; i < upperBound; i += LONG_SPECIES.length()) {
LongVector vector = LongVector.fromArray(LONG_SPECIES, array, i);
-
- // Check int compression using mask operations
- var maxMask = vector.compare(VectorOperators.GT, Integer.MAX_VALUE);
- var minMask = vector.compare(VectorOperators.LT, Integer.MIN_VALUE);
- if (maxMask.anyTrue() || minMask.anyTrue()) {
- canCompressToInt = false;
+ if (vector.compare(VectorOperators.GT, Integer.MAX_VALUE).anyTrue()
+ || vector.compare(VectorOperators.LT, Integer.MIN_VALUE).anyTrue()) {
+ return PrimitiveArrayCompressionType.NONE;
}
}
- // Handle remaining elements
- for (; i < array.length && canCompressToInt; i++) {
+ // Scalar tail for elements that do not fill a complete vector.
+ for (; i < array.length; i++) {
long value = array[i];
if (value > Integer.MAX_VALUE || value < Integer.MIN_VALUE) {
- canCompressToInt = false;
+ return PrimitiveArrayCompressionType.NONE;
}
}
-
- return canCompressToInt
- ? PrimitiveArrayCompressionType.LONG_TO_INT
- : PrimitiveArrayCompressionType.NONE;
+ return PrimitiveArrayCompressionType.LONG_TO_INT;
}
/**
- * Compress int array to byte array.
+ * Compresses an int array to a byte array.
*
- * @param array the int array to compress
+ * @param array the int array to compress; values must be in byte range
* @return compressed byte array
- * @throws NullPointerException if array is null
+ * @throws NullPointerException if {@code array} is null
*/
public static byte[] compressToBytes(int[] array) {
if (array == null) {
@@ -176,11 +156,11 @@ public final class ArrayCompressionUtils {
}
/**
- * Compress int array to short array.
+ * Compresses an int array to a short array.
*
- * @param array the int array to compress (values must be in short range)
+ * @param array the int array to compress; values must be in short range
* @return compressed short array
- * @throws NullPointerException if array is null
+ * @throws NullPointerException if {@code array} is null
*/
public static short[] compressToShorts(int[] array) {
if (array == null) {
@@ -194,11 +174,11 @@ public final class ArrayCompressionUtils {
}
/**
- * Compress long array to int array.
+ * Compresses a long array to an int array.
*
- * @param array the long array to compress (values must be in int range)
+ * @param array the long array to compress; values must be in int range
* @return compressed int array
- * @throws NullPointerException if array is null
+ * @throws NullPointerException if {@code array} is null
*/
public static int[] compressToInts(long[] array) {
if (array == null) {
@@ -212,11 +192,11 @@ public final class ArrayCompressionUtils {
}
/**
- * Decompress byte array to int array.
+ * Decompresses a byte array to an int array.
*
* @param array the byte array to decompress
* @return decompressed int array
- * @throws NullPointerException if array is null
+ * @throws NullPointerException if {@code array} is null
*/
public static int[] decompressFromBytes(byte[] array) {
if (array == null) {
@@ -230,11 +210,11 @@ public final class ArrayCompressionUtils {
}
/**
- * Decompress short array to int array.
+ * Decompresses a short array to an int array.
*
* @param array the short array to decompress
* @return decompressed int array
- * @throws NullPointerException if array is null
+ * @throws NullPointerException if {@code array} is null
*/
public static int[] decompressFromShorts(short[] array) {
if (array == null) {
@@ -248,17 +228,16 @@ public final class ArrayCompressionUtils {
}
/**
- * Decompress int array to long array.
+ * Decompresses an int array to a long array.
*
* @param array the int array to decompress
* @return decompressed long array
- * @throws NullPointerException if array is null
+ * @throws NullPointerException if {@code array} is null
*/
public static long[] decompressFromInts(int[] array) {
if (array == null) {
throw new NullPointerException("Array cannot be null");
}
-
long[] decompressed = new long[array.length];
for (int i = 0; i < array.length; i++) {
decompressed[i] = array[i];
diff --git
a/java/fory-simd/src/main/java/org/apache/fory/util/PrimitiveArrayCompressionType.java
b/java/fory-core/src/main/java16/org/apache/fory/util/PrimitiveArrayCompressionType.java
similarity index 82%
rename from
java/fory-simd/src/main/java/org/apache/fory/util/PrimitiveArrayCompressionType.java
rename to
java/fory-core/src/main/java16/org/apache/fory/util/PrimitiveArrayCompressionType.java
index 61e7c6fe6..477b2037b 100644
---
a/java/fory-simd/src/main/java/org/apache/fory/util/PrimitiveArrayCompressionType.java
+++
b/java/fory-core/src/main/java16/org/apache/fory/util/PrimitiveArrayCompressionType.java
@@ -23,18 +23,19 @@ package org.apache.fory.util;
* Compression types for primitive arrays.
*
* <p>Defines the available compression strategies for reducing the size of
primitive arrays by
- * detecting when values can fit in smaller data types.
+ * detecting when values can be stored with a narrower primitive type.
*/
public enum PrimitiveArrayCompressionType {
- // No compression applied
+ /** No compression applied. */
NONE(0),
- // Compression for int arrays:
- // int[] → byte[] compression (75% size reduction)
+ /** Compresses {@code int[]} values to {@code byte[]} when every value fits
in byte range. */
INT_TO_BYTE(1),
- // int[] → short[] compression (50% size reduction)
+
+ /** Compresses {@code int[]} values to {@code short[]} when every value fits
in short range. */
INT_TO_SHORT(2),
- // Compression for long arrays: long[] → int[] compression (50% size
reduction)
+
+ /** Compresses {@code long[]} values to {@code int[]} when every value fits
in int range. */
LONG_TO_INT(3);
private final int value;
@@ -46,7 +47,7 @@ public enum PrimitiveArrayCompressionType {
/**
* Gets the numeric value for this compression type.
*
- * @return the numeric value
+ * @return the numeric value written to the serialized payload
*/
public int getValue() {
return value;
@@ -55,7 +56,7 @@ public enum PrimitiveArrayCompressionType {
/**
* Gets the compression type from its numeric value.
*
- * @param value the numeric value
+ * @param value the numeric value read from the serialized payload
* @return the corresponding compression type
* @throws IllegalArgumentException if the value is not valid
*/
@@ -76,6 +77,8 @@ public enum PrimitiveArrayCompressionType {
/** Compression utilities for int arrays. Supports compression to byte[] and
short[] formats. */
public static final class IntArrayCompression {
+ private IntArrayCompression() {}
+
/**
* Determines the best compression type for the given int array.
*
@@ -97,7 +100,10 @@ public enum PrimitiveArrayCompressionType {
}
}
+ /** Compression utilities for long arrays. Supports compression to int[]
format. */
public static final class LongArrayCompression {
+ private LongArrayCompression() {}
+
/**
* Determines the best compression type for the given long array.
*
diff --git a/java/fory-core/src/main/java9/module-info.java
b/java/fory-core/src/main/java9/module-info.java
new file mode 100644
index 000000000..e381802ca
--- /dev/null
+++ b/java/fory-core/src/main/java9/module-info.java
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+module org.apache.fory.core {
+ requires java.logging;
+ requires jdk.unsupported;
+
+ requires static java.sql;
+ requires static com.google.common;
+ requires static org.slf4j;
+ requires static jsr305;
+
+ exports org.apache.fory;
+ exports org.apache.fory.annotation;
+ exports org.apache.fory.builder;
+ exports org.apache.fory.codegen;
+ exports org.apache.fory.collection;
+ exports org.apache.fory.config;
+ exports org.apache.fory.context;
+ exports org.apache.fory.exception;
+ exports org.apache.fory.io;
+ exports org.apache.fory.logging;
+ exports org.apache.fory.memory;
+ exports org.apache.fory.meta;
+ exports org.apache.fory.platform;
+ exports org.apache.fory.pool;
+ exports org.apache.fory.reflect;
+ exports org.apache.fory.resolver;
+ exports org.apache.fory.serializer;
+ exports org.apache.fory.serializer.collection;
+ exports org.apache.fory.serializer.converter;
+ exports org.apache.fory.serializer.scala;
+ exports org.apache.fory.serializer.struct;
+ exports org.apache.fory.type;
+ exports org.apache.fory.type.union;
+ exports org.apache.fory.type.unsigned;
+ exports org.apache.fory.util;
+ exports org.apache.fory.util.function;
+ exports org.apache.fory.util.record;
+ exports org.apache.fory.util.unsafe to
+ org.apache.fory.format;
+}
diff --git a/java/fory-format/pom.xml b/java/fory-format/pom.xml
index 01cdd773e..a1fecb2ef 100644
--- a/java/fory-format/pom.xml
+++ b/java/fory-format/pom.xml
@@ -106,6 +106,7 @@
<archive>
<manifestEntries>
<Automatic-Module-Name>org.apache.fory.format</Automatic-Module-Name>
+ <Multi-Release>true</Multi-Release>
</manifestEntries>
</archive>
</configuration>
@@ -121,6 +122,71 @@
</build>
<profiles>
+ <profile>
+ <id>jpms-java11</id>
+ <activation>
+ <jdk>[11,)</jdk>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <version>3.1.0</version>
+ <executions>
+ <execution>
+ <id>compile-java11-module-info</id>
+ <phase>process-classes</phase>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ <configuration>
+ <target>
+ <mkdir
dir="${project.build.directory}/jpms-classes/java11"/>
+ <path id="compile.module.path.elements">
+ <pathelement
location="${project.basedir}/../fory-core/target/jpms-classes/java9"/>
+ <path refid="maven.compile.classpath"/>
+ </path>
+ <pathconvert property="compile.module.path"
refid="compile.module.path.elements"
+ pathsep="${path.separator}"/>
+ <javac srcdir="${project.basedir}/src/main/java11"
+
destdir="${project.build.directory}/jpms-classes/java11"
+ includeantruntime="false"
+ fork="true"
+ executable="${java.home}/bin/javac"
+ debug="true">
+ <include name="module-info.java"/>
+ <compilerarg value="--release"/>
+ <compilerarg value="11"/>
+ <compilerarg value="--module-path"/>
+ <compilerarg path="${compile.module.path}"/>
+ <compilerarg value="--patch-module"/>
+ <compilerarg
value="org.apache.fory.format=${project.build.outputDirectory}"/>
+ </javac>
+ </target>
+ </configuration>
+ </execution>
+ <execution>
+ <id>inject-java11-module-info</id>
+ <phase>package</phase>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ <configuration>
+ <target>
+ <jar
destfile="${project.build.directory}/${project.build.finalName}.jar"
update="true">
+ <zipfileset
dir="${project.build.directory}/jpms-classes/java11"
+ prefix="META-INF/versions/11"
+ includes="module-info.class"/>
+ </jar>
+ </target>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
<profile>
<id>releaseShade</id>
<activation>
@@ -170,6 +236,8 @@
<filter>
<artifact>*:*</artifact>
<excludes>
+ <exclude>module-info.class</exclude>
+
<exclude>META-INF/versions/**/module-info.class</exclude>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
diff --git
a/java/fory-format/src/main/java/org/apache/fory/format/encoder/LazyArrayData.java
b/java/fory-format/src/main/java/org/apache/fory/format/encoder/LazyArrayData.java
index 38a9b92b5..c75f5b222 100644
---
a/java/fory-format/src/main/java/org/apache/fory/format/encoder/LazyArrayData.java
+++
b/java/fory-format/src/main/java/org/apache/fory/format/encoder/LazyArrayData.java
@@ -21,7 +21,7 @@ package org.apache.fory.format.encoder;
import static org.apache.fory.type.TypeUtils.getRawType;
-import java.awt.List;
+import java.util.List;
import org.apache.fory.annotation.Internal;
import org.apache.fory.codegen.ClosureVisitable;
import org.apache.fory.codegen.Code;
diff --git a/java/fory-format/src/main/java11/module-info.java
b/java/fory-format/src/main/java11/module-info.java
new file mode 100644
index 000000000..0f6064b8e
--- /dev/null
+++ b/java/fory-format/src/main/java11/module-info.java
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+
+module org.apache.fory.format {
+ requires transitive org.apache.fory.core;
+
+ requires static java.sql;
+ requires static transitive org.apache.arrow.memory.core;
+ requires static transitive org.apache.arrow.vector;
+
+ exports org.apache.fory.format.encoder;
+ exports org.apache.fory.format.row;
+ exports org.apache.fory.format.row.binary;
+ exports org.apache.fory.format.row.binary.writer;
+ exports org.apache.fory.format.type;
+ exports org.apache.fory.format.vectorized;
+}
diff --git a/java/fory-simd/pom.xml b/java/fory-simd/pom.xml
deleted file mode 100644
index 675e18374..000000000
--- a/java/fory-simd/pom.xml
+++ /dev/null
@@ -1,94 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-
- 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.
-
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <parent>
- <groupId>org.apache.fory</groupId>
- <artifactId>fory-parent</artifactId>
- <version>1.1.0-SNAPSHOT</version>
- </parent>
- <modelVersion>4.0.0</modelVersion>
-
- <artifactId>fory-simd</artifactId>
-
- <description>
- Apache Fory™ is a blazingly fast multi-language serialization
framework powered by jit and zero-copy.
- </description>
-
- <properties>
- <maven.compiler.source>17</maven.compiler.source>
- <maven.compiler.target>17</maven.compiler.target>
- <fory.java.rootdir>${basedir}/..</fory.java.rootdir>
- </properties>
-
- <dependencies>
- <dependency>
- <groupId>org.apache.fory</groupId>
- <artifactId>fory-core</artifactId>
- <version>${project.version}</version>
- </dependency>
-
- <!-- Test dependencies -->
- <dependency>
- <groupId>org.testng</groupId>
- <artifactId>testng</artifactId>
- <scope>test</scope>
- </dependency>
- </dependencies>
-
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- <configuration>
- <source>16</source>
- <target>16</target>
- <compilerArgs>
- <arg>--add-modules=jdk.incubator.vector</arg>
- </compilerArgs>
- </configuration>
- </plugin>
-
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-surefire-plugin</artifactId>
- <configuration>
- <argLine>--add-modules=jdk.incubator.vector</argLine>
- </configuration>
- </plugin>
-
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-javadoc-plugin</artifactId>
- <configuration>
- <!-- Turn this on once
https://github.com/apache/maven-javadoc-plugin/issues/1310 is resolved -->
- <failOnWarnings>false</failOnWarnings>
- <additionalOptions>
-
<additionalOption>--add-modules=jdk.incubator.vector</additionalOption>
- </additionalOptions>
- </configuration>
- </plugin>
- </plugins>
- </build>
-</project>
diff --git a/java/fory-testsuite/pom.xml b/java/fory-testsuite/pom.xml
index 7831d56dc..736307343 100644
--- a/java/fory-testsuite/pom.xml
+++ b/java/fory-testsuite/pom.xml
@@ -142,4 +142,63 @@
</plugins>
</build>
+ <profiles>
+ <profile>
+ <id>java16-compression-tests</id>
+ <activation>
+ <jdk>[16,)</jdk>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <version>3.1.0</version>
+ <executions>
+ <execution>
+ <id>compile-java16-compression-tests</id>
+ <phase>test-compile</phase>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ <configuration>
+ <target>
+ <mkdir dir="${project.build.testOutputDirectory}"/>
+ <pathconvert property="java16.test.classpath"
refid="maven.test.classpath"
+ pathsep="${path.separator}"/>
+ <javac srcdir="${project.basedir}/src/test/java16"
+ destdir="${project.build.testOutputDirectory}"
+
classpath="${project.basedir}/../fory-core/target/jpms-classes/java16${path.separator}${java16.test.classpath}"
+ includeantruntime="false"
+ fork="true"
+ executable="${java.home}/bin/javac"
+ debug="true">
+ <include name="**/*.java"/>
+ <compilerarg value="--source"/>
+ <compilerarg value="16"/>
+ <compilerarg value="--target"/>
+ <compilerarg value="16"/>
+ <compilerarg value="--add-modules"/>
+ <compilerarg value="jdk.incubator.vector"/>
+ </javac>
+ </target>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <argLine>--add-modules=jdk.incubator.vector</argLine>
+ <additionalClasspathElements>
+
<additionalClasspathElement>${project.basedir}/../fory-core/target/jpms-classes/java16</additionalClasspathElement>
+ </additionalClasspathElements>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
</project>
diff --git
a/java/fory-simd/src/test/java/org/apache/fory/serializer/ArrayCompressionTest.java
b/java/fory-testsuite/src/test/java16/org/apache/fory/serializer/ArrayCompressionTest.java
similarity index 99%
rename from
java/fory-simd/src/test/java/org/apache/fory/serializer/ArrayCompressionTest.java
rename to
java/fory-testsuite/src/test/java16/org/apache/fory/serializer/ArrayCompressionTest.java
index 665026410..a248b84c3 100644
---
a/java/fory-simd/src/test/java/org/apache/fory/serializer/ArrayCompressionTest.java
+++
b/java/fory-testsuite/src/test/java16/org/apache/fory/serializer/ArrayCompressionTest.java
@@ -29,7 +29,6 @@ import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
public class ArrayCompressionTest {
-
@DataProvider(name = "intArrayData")
public Object[][] intArrayData() {
return new Object[][] {
diff --git
a/java/fory-simd/src/test/java/org/apache/fory/serializer/ArrayCompressionUtilsTest.java
b/java/fory-testsuite/src/test/java16/org/apache/fory/serializer/ArrayCompressionUtilsTest.java
similarity index 99%
rename from
java/fory-simd/src/test/java/org/apache/fory/serializer/ArrayCompressionUtilsTest.java
rename to
java/fory-testsuite/src/test/java16/org/apache/fory/serializer/ArrayCompressionUtilsTest.java
index 29145b7a7..6c3b64a0a 100644
---
a/java/fory-simd/src/test/java/org/apache/fory/serializer/ArrayCompressionUtilsTest.java
+++
b/java/fory-testsuite/src/test/java16/org/apache/fory/serializer/ArrayCompressionUtilsTest.java
@@ -28,7 +28,6 @@ import org.apache.fory.util.PrimitiveArrayCompressionType;
import org.testng.annotations.Test;
public class ArrayCompressionUtilsTest {
-
@Test
public void testIntArrayCompressionDetection() {
// Test byte range compression - make array size >= 512
diff --git a/java/pom.xml b/java/pom.xml
index 4e1d14ae4..473b2c6a9 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -105,7 +105,6 @@
<jdk>[21,]</jdk>
</activation>
<modules>
- <module>fory-simd</module>
<module>fory-latest-jdk-tests</module>
</modules>
</profile>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]