例如,对于方法
function JsonObject<T>(initializer: (json: any) => T) {
return function (target: { new (...args: any[]): T }) {
return null;
}
}
@JsonObject(function (json) {
return new Foo();
})
class Foo {
foo: string;
}
@JsonObject(function (json) {
// Test case: return an exact corresponding type.
return new Bar(); // OK, as it should be
})
class Bar extends Foo {
bar: string;
}
@JsonObject(function (json) {
// Test case: return a derived type.
return new Baz(); // Ok
})
class Baz extends Bar {
baz: string;
}
public int f() {
int k = 1;
for (int i = 0; i < 10; i++) {
k += 2;
}
return k;
}
生成以下字节码:
javac
在标签4处,堆栈具有相同的大小(0),无论先前是哪个指令:3或16.
对于从java代码生成的字节码来说,这通常是正确的吗?
答案 0 :(得分:4)
有关锑的答案的参考,请参阅 JVM specification §4.9.2. Structural Constraints(谢谢Holger!):
- ...
- 如果一条指令可以沿着几条不同的执行路径执行,那么操作数堆栈必须在执行指令之前具有相同的深度(§2.6.2),无论采用何种路径。
在这个答案的第一个版本中,我引用了§4.10.2.1. The Process of Verification by Type Inference,它适用于不包含StackMapTable
属性(版本号为49.0或更低版本)的类文件:
...验证程序确保在程序中的任何给定点,无论采用何种代码路径达到该点,以下所有条件均为真:
- 操作数堆栈的大小始终相同,并包含相同类型的值。
- ...
答案 1 :(得分:3)
是。无论控制流如何,字节码验证都强制执行任何给定指令的堆栈大小。 (它还强制类型兼容)。因此,不仅从编译的Java派生的字节码,而且任何有效的字节码都是如此。