【发布时间】:2021-07-28 05:36:44
【问题描述】:
我是一名硕士生,我正在研究静态分析。 在我的一项测试中,我遇到了在 java 编译器中标记行的问题。
我有以下java代码:
226: String json = "/org/elasticsearch/index/analysis/commongrams/commongrams_query_mode.json";
227: Settings settings = Settings.settingsBuilder()
228: .loadFromStream(json, getClass().getResourceAsStream(json))
229: .put("path.home", createHome())
230: .build();
编译这段代码并执行命令javap -p -v CLASSNAME时,我得到一个表格,其中包含字节码中每条指令的源代码对应行。
见下图:
问题是在调用.put (" path.home ", createHome ())方法时,字节码基本上生成了4条指令:
19: anewarray
24: ldc - String path.home
30: invokespecial - createHome
34: invokevirtual - put
前两个标记为第 228 行(错误),后两个标记为第 229 行(正确)。
见下图:
这是.put("path.home", createHome())方法的原始实现:
public Builder put(Object... settings) {
if (settings.length == 1) {
// support cases where the actual type gets lost down the road...
if (settings[0] instanceof Map) {
//noinspection unchecked
return put((Map) settings[0]);
} else if (settings[0] instanceof Settings) {
return put((Settings) settings[0]);
}
}
if ((settings.length % 2) != 0) {
throw new IllegalArgumentException("array settings of key + value order doesn't hold correct number of arguments (" + settings.length + ")");
}
for (int i = 0; i < settings.length; i++) {
put(settings[i++].toString(), settings[i].toString());
}
return this;
}
我已经尝试使用 Oracle-JDK v8 和 Open-JDK v16 编译代码并在这两个结果中。
我还做了一个测试,通过删除其参数来更改put() 方法。编译此代码时,没有出现标记行的问题。
我想知道为什么字节码指令将229: .put (" path.home ", createHome ()) 行映射到Java 源代码中原始行之外的行上?有谁知道这是故意的吗?
【问题讨论】: