Skip to content

Fix IndexInputUtils.withSlice to produce native-safe MemorySegments on Java 21#143479

Merged
ChrisHegarty merged 2 commits intoelastic:mainfrom
ChrisHegarty:fix_withSlice_java21
Mar 3, 2026
Merged

Fix IndexInputUtils.withSlice to produce native-safe MemorySegments on Java 21#143479
ChrisHegarty merged 2 commits intoelastic:mainfrom
ChrisHegarty:fix_withSlice_java21

Conversation

@ChrisHegarty
Copy link
Copy Markdown
Contributor

On Java 21, FFI disallows passing heap-backed MemorySegments to native downcalls. Java 22+ removes this restriction.

IndexInputUtils.withSlice is now the single path through which all simdvec scorers obtain MemorySegments from IndexInput data, and several of those scorers pass the segment directly to native downcalls. Rather than patching each and every call site across scorer classes individually, this fix takes a "safety by design" approach: withSlice itself now guarantees that the segment it hands to callers is always native-safe, regardless of Java version. No current or future caller needs to worry about the heap-segment restriction, correctness is enforced at the source.

I also added an assertion to the DirectAccessInput path that the byte buffer is direct, documenting the invariant that real implementations always provide native-backed buffers.

The tradeoff here is that on Java 21 only, the copyAndApply fallback path incurs an extra native allocation and copy (via a confined Arena) where a heap-backed segment would have sufficed, since a number of call sites only use the Panama Vector API and never touch native downcalls. On Java 22+ the behavior is unchanged. This is an acceptable cost: the fallback path is already the slowest path (mmap and direct buffer paths are preferred), and the alternative - requiring every call site to independently guard against heap segments, is fragile and has already proven easy to miss. We can do some further cleanup at the call site after this fix has been merged.

caused by #141718
closes #143441

@ChrisHegarty ChrisHegarty added >refactoring :Search Relevance/Vectors Vector search Team:Search Relevance Meta label for the Search Relevance team in Elasticsearch labels Mar 3, 2026
@elasticsearchmachine
Copy link
Copy Markdown
Collaborator

Pinging @elastic/es-search-relevance (Team:Search Relevance)

try (Directory dir = new NIOFSDirectory(createTempDir())) {
writeData(dir, data);
try (IndexInput in = dir.openInput(FILE_NAME, IOContext.DEFAULT)) {
assertFalse(in instanceof MemorySegmentAccessInput);
Copy link
Copy Markdown
Member

@thecoop thecoop Mar 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assertThat(in, not(instanceOf(MemorySegmentAccessInput.class))), which will give you the actual type it is

Copy link
Copy Markdown
Member

@benwtrent benwtrent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am good with this

Copy link
Copy Markdown
Member

@thecoop thecoop left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, with one nit

Copy link
Copy Markdown
Contributor

@ldematte ldematte left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@ChrisHegarty ChrisHegarty merged commit d9f7082 into elastic:main Mar 3, 2026
31 of 35 checks passed
@ChrisHegarty ChrisHegarty deleted the fix_withSlice_java21 branch March 3, 2026 17:45
GalLalouche pushed a commit to GalLalouche/elasticsearch that referenced this pull request Mar 3, 2026
…n Java 21 (elastic#143479)

On Java 21, FFI disallows passing heap-backed MemorySegments to native downcalls. Java 22+ removes this restriction.

IndexInputUtils.withSlice is now the single path through which all simdvec scorers obtain MemorySegments from IndexInput data, and several of those scorers pass the segment directly to native downcalls. Rather than patching each and every call site across scorer classes individually, this fix takes a "safety by design" approach: withSlice itself now guarantees that the segment it hands to callers is always native-safe, regardless of Java version. No current or future caller needs to worry about the heap-segment restriction, correctness is enforced at the source.

I also added an assertion to the DirectAccessInput path that the byte buffer is direct, documenting the invariant that real implementations always provide native-backed buffers.

The tradeoff here is that on Java 21 only, the copyAndApply fallback path incurs an extra native allocation and copy (via a confined Arena) where a heap-backed segment would have sufficed, since a number of call sites only use the Panama Vector API and never touch native downcalls. On Java 22+ the behavior is unchanged. This is an acceptable cost: the fallback path is already the slowest path (mmap and direct buffer paths are preferred), and the alternative - requiring every call site to independently guard against heap segments, is fragile and has already proven easy to miss. We can do some further cleanup at the call site after this fix has been merged.

caused by elastic#141718
closes elastic#143441
szybia added a commit to szybia/elasticsearch that referenced this pull request Mar 3, 2026
…locations

* upstream/main: (51 commits)
  ESQL: Remaining serialization tests (elastic#143470)
  Eagerly release resources in `TransportAwaitClusterStateVersionAppliedAction` (elastic#143477)
  Stop and relocate sliced reindex on shutdown (elastic#143183)
  Documentation for query_vector base64 parameter (elastic#142675)
  ES|QL: Fix LIMIT after all columns are dropped (elastic#143463)
  Update docs-build.yml (elastic#142958)
  Fix KnnIndexTester to work with byte vectors (elastic#143493)
  Fix IndexInputUtils.withSlice to produce native-safe MemorySegments on Java 21 (elastic#143479)
  CPS fix: include only relevant projects in the search response metadata (elastic#143367)
  apm-data: explicit map of timestamp.us to long (elastic#143173)
  [Inference API] Add custom headers for Azure OpenAI Service (elastic#142969)
  ESQL: Add name IDs to golden tests and fix synthetic names (elastic#143450)
  Add getUnavailableShards to BaseBroadcastResponse (elastic#143406)
  Add description to reindex API without sensitive info (elastic#143112)
  SQL: fix CLI tests (elastic#143451)
  ES|QL: Add note of future removal of FORK implicit LIMIT (elastic#143457)
  [Test] Randomly disable doc values skippers in time-series indices (elastic#143389)
  Improve pattern text downgrade license test (elastic#143102)
  [Transform] Stop transforms at the end of tests (elastic#139783)
  Mute org.elasticsearch.compute.lucene.read.ValueSourceReaderTypeConversionTests testLoadAll elastic#143471
  ...
shmuelhanoch pushed a commit to shmuelhanoch/elasticsearch that referenced this pull request Mar 4, 2026
…n Java 21 (elastic#143479)

On Java 21, FFI disallows passing heap-backed MemorySegments to native downcalls. Java 22+ removes this restriction.

IndexInputUtils.withSlice is now the single path through which all simdvec scorers obtain MemorySegments from IndexInput data, and several of those scorers pass the segment directly to native downcalls. Rather than patching each and every call site across scorer classes individually, this fix takes a "safety by design" approach: withSlice itself now guarantees that the segment it hands to callers is always native-safe, regardless of Java version. No current or future caller needs to worry about the heap-segment restriction, correctness is enforced at the source.

I also added an assertion to the DirectAccessInput path that the byte buffer is direct, documenting the invariant that real implementations always provide native-backed buffers.

The tradeoff here is that on Java 21 only, the copyAndApply fallback path incurs an extra native allocation and copy (via a confined Arena) where a heap-backed segment would have sufficed, since a number of call sites only use the Panama Vector API and never touch native downcalls. On Java 22+ the behavior is unchanged. This is an acceptable cost: the fallback path is already the slowest path (mmap and direct buffer paths are preferred), and the alternative - requiring every call site to independently guard against heap segments, is fragile and has already proven easy to miss. We can do some further cleanup at the call site after this fix has been merged.

caused by elastic#141718
closes elastic#143441
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

>refactoring :Search Relevance/Vectors Vector search Team:Search Relevance Meta label for the Search Relevance team in Elasticsearch v9.4.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[CI] ESNextOSQVectorsScorerTests class failing

5 participants