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

Java 19中如何声明值类型类及判断编译器决策?

Java 19 自定义值类型栈分配的实现与编译器决策验证

一、关于@jdk.internal.ValueBased的问题

这个注解是JDK内部API,属于jdk.internal模块,默认对外不暴露,自定义类无法直接通过它标记值类型。Java 19中值类型的声明有标准语法和规则,不需要依赖内部注解。

二、正确声明值类型的方式

Java 19通过JEP 401引入了**值对象(Value Objects)**预览特性,同时record类天然具备值类型的属性,两种方式都能让编译器识别为值类型候选,进而进行栈分配优化:

方式1:使用value class(预览特性)

需要启用预览特性编译,类必须满足不可变要求:

// 编译时需添加参数:--enable-preview --release 19
value class Point {
    private final int x;
    private final int y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Point point = (Point) o;
        return x == point.x && y == point.y;
    }

    @Override
    public int hashCode() {
        return Objects.hash(x, y);
    }
}

方式2:使用record(更简洁,天然值类型)

record自动满足final类、所有字段final、生成基于字段的equals()/hashCode(),无需额外配置:

record Point(int x, int y) {}

三、验证编译器的栈分配决策

要确认编译器是否将你的类视为值类型并进行栈分配,可以通过以下方法:

  • 查看字节码
    用javap -c -v YourClass.class命令解析字节码。如果对象被栈分配,方法中不会出现new指令(堆分配的标志),而是直接通过局部变量操作(astore/aload)处理对象。

  • 启用逃逸分析日志
    运行程序时添加JVM参数:-XX:+PrintEscapeAnalysis -XX:+PrintEliminateAllocations,控制台会输出逃逸分析结果。如果值类型对象未逃逸出方法,会看到类似Eliminated allocation of ...的日志,说明已进行栈分配。

  • 查看JIT编译日志
    添加参数-XX:+PrintCompilation -XX:+PrintInlining,可以查看JIT编译后的优化细节,确认值类型是否被栈分配。

四、关键注意事项

  • value class是预览特性,编译和运行时都需要添加--enable-preview参数。
  • 栈分配的前提是对象未逃逸出当前方法,如果对象被返回、传递给外部方法或存入全局变量,JVM仍会将其分配在堆上。
  • 手动编写的值类型类必须严格遵循不可变规则:类用final修饰、所有实例字段为final、无可变状态,否则编译器不会将其纳入值类型候选。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 19:46:01