Skip to content

Commit ea1ac84

Browse files
dfa1claude
andcommitted
fix: shrink native jars and harden platform detection
Strip the symbol/debug tables from the ELF shared library at link time (-s): an unstripped libzstd.so carried full debug_info and was ~6x larger than needed (4.0M -> ~650K). Delete the .pdb (multi-MB debug database) and .lib import library that lld emits next to a Windows .dll; neither is needed at runtime and both were being bundled into the native JAR. Net effect: the linux-x86_64 native jar drops 1.2M -> 285K and windows-x86_64 1.2M -> 372K. Harden NativeLibrary.classifier(): an unrecognized CPU arch silently mapped to x86_64, deferring failure to a cryptic dlopen error. Now throw a clear UnsatisfiedLinkError naming the unsupported arch, with an explicit amd64 branch so Linux JVMs (which report os.arch=amd64) still resolve x86_64. Normalize blank-line separators between independent handle blocks in Bindings (the frame/skippable cluster was packed unlike the rest of the file). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 0c74b4c commit ea1ac84

3 files changed

Lines changed: 31 additions & 3 deletions

File tree

scripts/build-zstd.sh

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,14 @@ trap 'rm -rf "$WORK"' EXIT
7575
# symbol into the PE export table (the classic, reliable MinGW DLL path).
7676
VIS_FLAG="-fvisibility=hidden"
7777
LINK_EXTRA=""
78+
# Strip the symbol/debug tables at link time. An unstripped ELF .so carries full
79+
# debug_info and is ~6x larger than needed (4.0M -> ~250K); -s drops it. PE/COFF
80+
# keeps its exports in the export table (separate from the symbol table), but
81+
# lld still emits a multi-megabyte .pdb and an import .lib next to the .dll —
82+
# those are deleted after the link below rather than suppressed via strip.
83+
STRIP_FLAG="-s"
7884
case "$CLASSIFIER" in
79-
windows-*) VIS_FLAG=""; LINK_EXTRA="-Wl,--export-all-symbols" ;;
85+
windows-*) VIS_FLAG=""; LINK_EXTRA="-Wl,--export-all-symbols"; STRIP_FLAG="" ;;
8086
esac
8187
CFLAGS="-O3 -DNDEBUG -DZSTD_DISABLE_ASM=1 -DXXH_NAMESPACE=ZSTD_ $VIS_FLAG \
8288
-I$ZSTD_LIB -I$ZSTD_LIB/common -fPIC"
@@ -95,6 +101,11 @@ wait
95101
SONAME_FLAG=""
96102
[ "$LIB_NAME" = "libzstd.so" ] && SONAME_FLAG="-Wl,-soname,libzstd.so.1"
97103

98-
zig cc -target "$ZIG_TARGET" -shared $SONAME_FLAG $LINK_EXTRA -o "$DEST_DIR/$LIB_NAME" "$WORK"/*.o
104+
zig cc -target "$ZIG_TARGET" -shared $STRIP_FLAG $SONAME_FLAG $LINK_EXTRA -o "$DEST_DIR/$LIB_NAME" "$WORK"/*.o
105+
106+
# lld emits a .pdb (debug database, multiple MB) and a .lib (import library) next
107+
# to a Windows .dll; neither is needed at runtime and both would be bundled into
108+
# the native JAR. Keep only the shared library itself in the resources directory.
109+
find "$DEST_DIR" -type f ! -name "$LIB_NAME" -delete
99110

100111
echo "[build-zstd] Installed: $DEST_DIR/$LIB_NAME"

zstd/src/main/java/io/github/dfa1/zstd/Bindings.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,30 +43,37 @@ final class Bindings {
4343
// unsigned ZSTD_isFrame(const void* buffer, size_t size)
4444
static final MethodHandle IS_FRAME =
4545
NativeLibrary.lookup("ZSTD_isFrame", FunctionDescriptor.of(JAVA_INT, ADDRESS, JAVA_LONG));
46+
4647
// size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize)
4748
static final MethodHandle FIND_FRAME_COMPRESSED_SIZE =
4849
NativeLibrary.lookup("ZSTD_findFrameCompressedSize",
4950
FunctionDescriptor.of(JAVA_LONG, ADDRESS, JAVA_LONG));
51+
5052
// unsigned long long ZSTD_decompressBound(const void* src, size_t srcSize)
5153
static final MethodHandle DECOMPRESS_BOUND =
5254
NativeLibrary.lookup("ZSTD_decompressBound",
5355
FunctionDescriptor.of(JAVA_LONG, ADDRESS, JAVA_LONG));
56+
5457
// unsigned ZSTD_getDictID_fromFrame(const void* src, size_t srcSize)
5558
static final MethodHandle GET_DICT_ID_FROM_FRAME =
5659
NativeLibrary.lookup("ZSTD_getDictID_fromFrame",
5760
FunctionDescriptor.of(JAVA_INT, ADDRESS, JAVA_LONG));
61+
5862
// size_t ZSTD_getFrameHeader(ZSTD_FrameHeader* zfh, const void* src, size_t srcSize)
5963
static final MethodHandle GET_FRAME_HEADER =
6064
NativeLibrary.lookup("ZSTD_getFrameHeader",
6165
FunctionDescriptor.of(JAVA_LONG, ADDRESS, ADDRESS, JAVA_LONG));
66+
6267
// unsigned ZSTD_isSkippableFrame(const void* buffer, size_t size)
6368
static final MethodHandle IS_SKIPPABLE_FRAME =
6469
NativeLibrary.lookup("ZSTD_isSkippableFrame",
6570
FunctionDescriptor.of(JAVA_INT, ADDRESS, JAVA_LONG));
71+
6672
// size_t ZSTD_writeSkippableFrame(void* dst, size_t dstCap, const void* src, size_t srcSize, unsigned magicVariant)
6773
static final MethodHandle WRITE_SKIPPABLE_FRAME =
6874
NativeLibrary.lookup("ZSTD_writeSkippableFrame",
6975
FunctionDescriptor.of(JAVA_LONG, ADDRESS, JAVA_LONG, ADDRESS, JAVA_LONG, JAVA_INT));
76+
7077
// size_t ZSTD_readSkippableFrame(void* dst, size_t dstCap, unsigned* magicVariant, const void* src, size_t srcSize)
7178
static final MethodHandle READ_SKIPPABLE_FRAME =
7279
NativeLibrary.lookup("ZSTD_readSkippableFrame",
@@ -83,6 +90,7 @@ final class Bindings {
8390
// ZSTD_ErrorCode ZSTD_getErrorCode(size_t functionResult)
8491
static final MethodHandle GET_ERROR_CODE =
8592
NativeLibrary.lookup("ZSTD_getErrorCode", FunctionDescriptor.of(JAVA_INT, JAVA_LONG));
93+
8694
// const char* ZSTD_getErrorString(ZSTD_ErrorCode code)
8795
static final MethodHandle GET_ERROR_STRING =
8896
NativeLibrary.lookup("ZSTD_getErrorString", FunctionDescriptor.of(ADDRESS, JAVA_INT));

zstd/src/main/java/io/github/dfa1/zstd/NativeLibrary.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,16 @@ private static String classifier() {
9595
} else {
9696
osName = "linux";
9797
}
98-
String archName = (arch.equals("aarch64") || arch.equals("arm64")) ? "aarch64" : "x86_64";
98+
String archName;
99+
if (arch.equals("aarch64") || arch.equals("arm64")) {
100+
archName = "aarch64";
101+
} else if (arch.equals("x86_64") || arch.equals("amd64")) {
102+
archName = "x86_64";
103+
} else {
104+
throw new UnsatisfiedLinkError(
105+
"Unsupported CPU architecture '" + arch + "'; zstd-java ships native libraries "
106+
+ "only for x86_64 and aarch64");
107+
}
99108
return osName + "-" + archName;
100109
}
101110

0 commit comments

Comments
 (0)