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

如何在javac编译Java代码时禁用constant folding(常量折叠)?

如何禁用javac的常量折叠以保留分步相加的字节码

核心结论

javac本身没有官方编译选项可以直接禁用常量折叠——这是Java语言规范(JLS)要求的编译期行为,对于编译期可确定的常量表达式,javac必须在编译阶段完成求值。

绕过方案

要得到你想要的分步相加字节码,需要将代码中的字面量转换为非编译期常量,让javac无法在编译阶段直接计算出最终结果,具体有两种常用方式:

方式1:使用局部变量存储字面量

修改代码为:

public class App{
  public int sum(){
    int a = 1;
    int b = 2;
    int c = 3;
    int d = 4;
    return (a + b) + (c + d);
  }
}

编译后用javap -v App查看sum方法的字节码,会得到包含分步相加的指令:

0: iconst_1
1: istore_1
2: iconst_2
3: istore_2
4: iconst_3
5: istore_3
6: iconst_4
7: istore        4
9: iload_1
10: iload_2
11: iadd
12: iload_3
13: iload        4
15: iadd
16: iadd
17: ireturn

注:这里多了istore和iload指令用于变量的存储与加载,但核心的三次iadd操作完全保留。

方式2:使用方法返回字面量

如果希望避免局部变量的存储指令,可以通过方法调用返回字面量,让javac无法在编译期确定结果:

public class App{
  private static int getOne() { return 1; }
  private static int getTwo() { return 2; }
  private static int getThree() { return 3; }
  private static int getFour() { return 4; }

  public int sum(){
    return (getOne() + getTwo()) + (getThree() + getFour());
  }
}

对应的字节码会包含方法调用指令和后续的分步相加操作。

补充说明

常量折叠是javac遵循JLS规范的必然行为,JLS明确要求编译期对所有常量表达式进行求值并替换为最终常量值,因此官方没有提供禁用该优化的开关。上述方案本质是通过破坏"编译期常量表达式"的条件,让javac只能生成分步执行的字节码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 09:57:43