gpt4 book ai didi

java对Byte的按位运算

转载 作者:搜寻专家 更新时间:2023-11-01 03:04:15 25 4
gpt4 key购买 nike

public static void main(String[] args) throws Exception {
for (int i = 0, k = 20; i < Integer.MAX_VALUE; i++) {
final Byte b = (byte) -1; // new Byte((byte) -1) works fine
final int x = b.byteValue() & 0xff;
if (x == -1) System.out.println(x + " is -1 (" + i + ")");
if (x != 255) {
System.out.println(x + " is not 255 (" + i + ")");
if (x == -1) System.out.println(x + " is not 255 but -1 (" + i + ")");
if (--k == 0) break;
}
if (i % 100 == 0) Thread.sleep(1); // or other operations to make this code run slower
}
}

一次运行的输出:

-1 is not 255 (110675)
-1 is not 255 but -1 (110675)
/ is not 255 (168018)
/ is not 255 (168019)
/ is not 255 (168020)
/ is not 255 (168021)
/ is not 255 (168022)
/ is not 255 (168023)
/ is not 255 (168024)
/ is not 255 (168025)
/ is not 255 (168026)
/ is not 255 (168027)
/ is not 255 (168028)
/ is not 255 (168029)
/ is not 255 (168030)
/ is not 255 (168031)
/ is not 255 (168032)
/ is not 255 (168033)
/ is not 255 (168034)
/ is not 255 (168035)
/ is not 255 (168036)

谁能解释一下输出结果。测试必须在 jdk1.8.0_20 或 jdk1.8.0_25 或 jdk1.8.0_31 上运行并带有“-server”选项。我认为这是一个错误,我已经向 oracle 提交了错误报告,但还没有收到回复。

最佳答案

我想我找到了导致此行为的问题;它以 bug 8042786 的形式提交给 OpenJDK。并且确实与自动装箱有关。使用 -XX:-EliminateAutoBox 运行 Java 似乎是一个有效的解决方法,可以使这个问题消失。

它被标记为已解决。链接的错误报告很有趣,该错误显然最初是在 a SO question 中发现的。 .

编辑:

从有这个问题的虚拟机的错误报告和编译日志来看,这是我对发生的事情的分析,更准确地说,发生了什么:

对于前 110674 次迭代,代码在解释器中运行并由没有此错误的 C1 编译器编译,但之后,C2 编译器开始将 main 替换为一个更优化的版本。在第一轮编译中,C2 执行以下操作:

  • 从表达式 b.byteValue() & 0xff 得出 x 介于 0 和 255 之间的结论。因此,测试 x = = -1 不能为真,并被优化掉。
  • 此时,类 java.lang.System 仍未加载,因此所有对 System.out.println 的调用都被替换为陷阱取消优化该方法并恢复为等待类加载和重新编译的解释器。
  • 为了评估 b.byteValue() & 0xff 表达式,编译器足够智能,可以内联一个无符号内存字节加载,从内存中获取值,而无需执行以下操作 and 操作,因此单条指令应该填充 x 的值,但这是编译器 bug 出现的地方,错误地将其替换为带符号的加载(a movsbl 指令)。所以 x 实际上加载了完整的符号扩展到 32 位,但是编译器已经假定 x 的值在 0-255 范围内。

然后发生的是 x == -1 测试不会触发,因为 C2 已将其优化掉,但 x != 255 测试会触发,因为编译器不够聪明,无法看到 x 应该始终为 255(我确实觉得这有点奇怪,因为 Byte.valueOf()b. byteValue() 已被内联,但显然它就是这样)。当它进入以下子句时,代码尝试加载 System.out,这会立即取消优化代码,加载类,并在解释器中完成迭代。这就是为什么 x 在本次迭代的其余部分被“正确地”视为 -1 的原因。

然后循环继续在解释器和 C1 编译的代码中进行另外几千次迭代,直到 C2 再次启动以重新优化现在加载了 java.lang.System 的代码。然后会发生以下情况:

  • 同样,x == -1 的测试被优化为不可能。
  • 但是,这次 java.lang.System 被加载,格式 x + "is not 255 ("+ i + ")" 的调用被内联.查看 Integer.toString() 的源代码,这意味着消除了对负整数输出的测试(同样,因为 x 被确定为正数),并且因此 x 被格式化为 1 位正数(因为它小于 10)。因此,这一位输出为'0' + -1;即,作为 /

这可能充其量只是琐事,但它引起了我的注意。 :)

关于java对Byte的按位运算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28194061/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com