You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java 22升级至23时堆外内存访问越界问题求助

Java 23堆外内存VarHandle访问触发IndexOutOfBoundsException问题

将Java版本从22升级至23后,涉及堆外内存操作的业务代码出现异常,具体情况如下:

核心异常代码

val intVh = MemoryLayout
    .sequenceLayout(
      Long.MaxValue / ValueLayout.JAVA_INT.byteSize(),
      ValueLayout.JAVA_INT,
    )
    .varHandle(PathElement.sequenceElement())

@IntrinsicCandidate
@inline
def set[R <: Global](mem: Memory[L, R], value: Int, x1: Int)(
  implicit
  region: Region[R],
): Unit = {
  intVh.set(mem.asJava, vh.offset0 + vh.step1 * x1 + vh.offset1, 0L, value)
}

异常信息

Java 22环境测试正常,但升级到23后触发IndexOutOfBoundsException:

Assertion failed:
  Exception in thread "zio-fiber-71,58,53" java.lang.IndexOutOfBoundsException: Out of bound access on segment MemorySegment{ address: 0x60000228f000, byteSize: 40 }; new offset = 0; new length = 9223372036854775804
    at java.base/jdk.internal.foreign.AbstractMemorySegmentImpl.outOfBoundException(AbstractMemorySegmentImpl.java:439)
    ...(省略部分栈帧)

修复后正常代码

修改为直接调用MemorySegment的set方法后,Java 22和23环境下均正常运行:

mem
   .asJava
   .set(
      ValueLayout.JAVA_INT,
      vh.offset0 + vh.step1 * x1 + vh.offset1,
      value,
     )

补充信息

  • mem.asJava为MemorySegment实例
  • 实际访问的偏移量范围为0到10
  • 代码中传入0L是之前为规避OpenJ9的某个问题而添加的写法

问题分析

Java 23对堆外内存API的边界校验逻辑做了关键变更:

  1. 原代码创建的sequenceLayout长度为Long.MaxValue / 4(约2.3e18),远大于实际使用的MemorySegment(仅40字节)
  2. Java 22中,通过该布局生成的VarHandle访问内存时,未严格校验布局总长度与内存段实际长度的匹配关系
  3. Java 23开始,VarHandle会结合关联的布局总长度做合法性校验——当内存段长度远小于布局长度时,直接判定为越界访问
  4. MemorySegment.set方法仅基于内存段自身的边界做校验,只要偏移量在内存段范围内即可正常执行,因此不受布局长度影响

内容的提问来源于stack exchange,提问作者Person Person

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 10:24:56