wangyum opened a new issue, #15930:
URL: https://github.com/apache/iceberg/issues/15930
## Problem
When attempting to run Apache Iceberg on Java 25, the Arrow memory subsystem
fails to initialize with an `ExceptionInInitializerError`. The build currently
gates on Java 17 or 21 (`build.gradle:54`), but attempting to support Java 25
surfaces an incompatibility deep in the Arrow/Netty stack.
## Environment
- **Java version**: 25
- **Apache Iceberg version**: `main` branch (1.9.0-SNAPSHOT)
- **Arrow version**: 15.0.2
- **Netty version**: 4.2.12.Final
## Stack Trace
```
java.lang.ExceptionInInitializerError
at
org.apache.arrow.memory.DefaultAllocationManagerFactory.<clinit>(DefaultAllocationManagerFactory.java:26)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:467)
at java.base/java.lang.Class.forName(Class.java:458)
at
org.apache.arrow.memory.DefaultAllocationManagerOption.getFactory(DefaultAllocationManagerOption.java:108)
at
org.apache.arrow.memory.DefaultAllocationManagerOption.getDefaultAllocationManagerFactory(DefaultAllocationManagerOption.java:98)
at
org.apache.arrow.memory.BaseAllocator$Config.getAllocationManagerFactory(BaseAllocator.java:773)
at
org.apache.arrow.memory.ImmutableConfig.access$801(ImmutableConfig.java:24)
at
org.apache.arrow.memory.ImmutableConfig$InitShim.getAllocationManagerFactory(ImmutableConfig.java:83)
at
org.apache.arrow.memory.ImmutableConfig.<init>(ImmutableConfig.java:47)
at
org.apache.arrow.memory.ImmutableConfig.<init>(ImmutableConfig.java:24)
at
org.apache.arrow.memory.ImmutableConfig$Builder.build(ImmutableConfig.java:485)
at org.apache.arrow.memory.BaseAllocator.<clinit>(BaseAllocator.java:62)
at Reproducer.main(Reproducer.java:8)
Caused by: java.lang.UnsupportedOperationException
at io.netty.buffer.EmptyByteBuf.memoryAddress(EmptyByteBuf.java:961)
at
io.netty.buffer.DuplicatedByteBuf.memoryAddress(DuplicatedByteBuf.java:115)
at
io.netty.buffer.UnsafeDirectLittleEndian.<init>(UnsafeDirectLittleEndian.java:55)
at
io.netty.buffer.UnsafeDirectLittleEndian.<init>(UnsafeDirectLittleEndian.java:40)
at
io.netty.buffer.PooledByteBufAllocatorL.<init>(PooledByteBufAllocatorL.java:50)
at
org.apache.arrow.memory.NettyAllocationManager.<clinit>(NettyAllocationManager.java:51)
... 14 more
```
## Root Cause
The failure originates in `NettyAllocationManager`'s static initializer,
which instantiates `PooledByteBufAllocatorL`. That allocator internally
constructs a `UnsafeDirectLittleEndian` wrapper and probes the native memory
address of a `DuplicatedByteBuf(EmptyByteBuf)`. On Java 25, the
`sun.misc.Unsafe` direct memory access path used by older Netty is broken for
this use case, causing `EmptyByteBuf.memoryAddress()` to throw
`UnsupportedOperationException`.
This is a layered incompatibility:
1. **Netty 4.x** (pre-5.0) relies on `sun.misc.Unsafe` for native direct
memory address resolution.
2. **Java 21+** increasingly restricts these patterns, and **Java 25** (with
[JEP 471](https://openjdk.org/jeps/471) deprecating `Unsafe` memory-access
methods for removal) breaks them outright.
3. **Arrow 15.0.2** depends on this legacy Netty allocator path via
`arrow-memory-netty`.
The `iceberg-arrow` module pulls in both `arrow-memory-netty` and
`arrow-memory-unsafe`, both of which use the failing static initializer path
through `BaseAllocator`.
## Affected Code
- `build.gradle:54` — Java version guard (currently rejects anything other
than JDK 17/21 at build time)
- `build.gradle:951-958` — `iceberg-arrow` depends on `arrow-memory-netty`
and `arrow-memory-unsafe`
- `libs.versions.toml:32` — `arrow = "15.0.2"`
- `libs.versions.toml:79` — `netty-buffer = "4.2.12.Final"`
## Possible Solutions
1. **Upgrade Arrow** — Arrow 16+ or later may include fixes for Java 21/25
compatibility that avoid the broken `PooledByteBufAllocatorL` initialization.
This is the most sustainable path.
2. **Use the `arrow-memory-unsafe` allocator exclusively** — Arrow provides
a Netty-free allocator path. Setting the system property
`-Darrow.memory.allocator=unsafe` or restructuring dependencies to rely solely
on `arrow-memory-unsafe` (bypassing `arrow-memory-netty`) may avoid the failing
static initializer.
3. **Extend the Java version guard** — Regardless of the dependency fix
chosen, `build.gradle:54` needs to be updated to allow Java 25 once the
underlying incompatibility is resolved.
## References
- [JEP 471: Deprecate the Memory-Access Methods in sun.misc.Unsafe for
Removal](https://openjdk.org/jeps/471)
- [Apache Arrow Java compatibility
tracking](https://github.com/apache/arrow/issues)
- Netty issue: `PooledByteBufAllocatorL` unsafe memory access broken on
modern JDKs
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]