一尘不染

是否可以禁用静态最终变量的javac内联?

java

Java静态编译器(javac)内联一些静态最终变量,并将值直接带到常量池中。考虑以下示例。A类定义了一些常量(公共静态最终变量):

public class A {
    public static final int INT_VALUE = 1000;
    public static final String STRING_VALUE = "foo";
}

B类使用以下常量:

public class B {
    public static void main(String[] args) {
        int i = A.INT_VALUE;
        System.out.println(i);
        String s = A.STRING_VALUE;
        System.out.println(s);
    }
}

当您编译类B时,javac从类A获取这些常量的值,并在B.class中内联这些值。结果,在编译时必须将类A的依赖项B从字节码中删除。这是一个非常特殊的行为,因为在
编译时 要烘焙这些常量的值。您可能会认为这是JIT编译器在运行时可以做的最简单的事情之一。

有什么方法或任何隐藏的编译器选项可让您禁用Javac的这种内联行为吗?对于背景,我们正在考虑进行字节码分析以实现依赖关系,这是字节码分析无法检测到编译时依赖关系的少数情况之一。谢谢!

编辑 :这是一个令人烦恼的问题,因为通常我们不控制所有源代码(例如,定义常量的第三方库)。我们有兴趣从 使用
常量的角度检测这些依赖关系。由于从 使用 常量的代码中删除了引用,因此没有简单的方法可以检测到它们,而无需进行源代码分析。


阅读 242

收藏
2020-09-08

共1个答案

一尘不染

Java Puzzlers(Joshua Bloch)的第93项说,您可以通过防止将最终值视为常量来解决此问题。例如:

public class A {
  public static final int INT_VALUE = Integer.valueOf(1000).intValue();
  public static final String STRING_VALUE = "foo".toString();
}

当然,如果您无权访问定义常量的代码,则这些都不相关。

2020-09-08