问题描述
Java静态编译器(javac)会嵌入一些静态的最终变量,并将值直接引导到常量池。请考虑以下示例。 A类定义了一些常量(public static final variables): 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中包含这些值。因此,编译时的依赖关系B必须等级A从字节码中被清除。这是一个相当特殊的行为,因为您正在编译时使用这些常量的值进行烘焙。你会认为这是JIT编译器在运行时可以做的最简单的事情之一。
有什么方法或任何隐藏的编译器选项可以禁用这个javac的内联行为?对于后台,我们正在研究为依赖目的进行字节码分析,而且它是字节码分析无法检测编译时依赖关系的少数情况之一。谢谢!
编辑:这是一个令人烦恼的问题,因为通常我们不控制所有的源代码(例如定义常量的第三方库)。我们有兴趣从使用常量的角度检测这些依赖关系。由于引用从使用常量的代码中删除,所以没有简单的方法可以检测它们,而不用进行源代码分析。
项目93的Java拼图程序(Joshua Bloch)说,你可以通过防止最终的值被认为是常数来解决这个问题。例如:
public class A {
public static final int INT_VALUE = Integer.valueOf(1000).intValue );
public static final String STRING_VALUE =foo.toString();
}
当然,如果您无法访问代码定义常量。
The Java static compiler (javac) inlines some static final variables and brings the values directly to the constant pool. Consider the following example. Class A defines some constants (public static final variables):
public class A {
public static final int INT_VALUE = 1000;
public static final String STRING_VALUE = "foo";
}
Class B uses these constants:
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);
}
}
When you compile class B, javac gets the values of these constants from class A and inlines these values in B.class. As a result, the dependency B had to class A at the compile time is erased from the bytecode. This is a rather peculiar behavior because you are baking in the values of these constants at the time of compilation. And you would think that this is one of the easiest things that the JIT compiler can do at runtime.
Is there any way or any hidden compiler option that lets you disable this inlining behavior of javac? For the background, we're looking into doing bytecode analysis for dependency purposes, and it is one of the few cases where bytecode analysis fails to detect compile-time dependencies. Thanks!
Edit: this is a vexing issue because normally we don't control all the source (e.g. third-party libraries that define constants). We're interested in detecting these dependencies from the perspective of using the constants. Since the reference is erased from the code that uses the constants, there is no easy way to detect them, short of doing source code analysis.
Item 93 of Java Puzzlers (Joshua Bloch) says that you can work round this by preventing the final value from being considered a constant. For example:
public class A {
public static final int INT_VALUE = Integer.valueOf(1000).intValue();
public static final String STRING_VALUE = "foo".toString();
}
Of course none of this is relevant if you don't have access to the code that defines the constants.
这篇关于是否可以禁用javac的静态final变量的内联?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!