如何使JVM跳转指令的偏移量为32768? [英] How can the offset for a JVM jump instruction be 32768?

查看:418
本文介绍了如何使JVM跳转指令的偏移量为32768?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在撰写关于JVM字节代码偏移问题的答案时,我注意到了javac的行为和我不能解释的结果类文件:

While writing an answer to a question about JVM byte code offsets, I noticed something in the behavior of javac and the resulting class files that I can not explain:

当编译类似这样的类时

class FarJump
{
    public static void main(String args[])
    {
        call(0, 1);
    }

    public static void call(int x, int y)
    {
        if (x < y)
        {
            y++;
            y++;

            // ... (10921 times - too much code to post here!)

            y++;
            y++;
        }
        System.out.println(y);
    }

}

以下 if_icmpge 指令:

public static void call(int, int);
    Code:
       0: iload_0
       1: iload_1
       2: if_icmpge     32768
       5: iinc          1, 1
       8: iinc          1, 1
       ...

根据跳转指令的文档,偏移(32768这种情况)计算如下:

According to the documentation of the jump instructions, the offset (which is 32768 in this case) is computed as follows:


如果比较成功,则无符号 branchbyte1 branchbyte2 用于构造有符号16位偏移,其中偏移被计算为(branchbyte1 <<8)| branchbyte2

If the comparison succeeds, the unsigned branchbyte1 and branchbyte2 are used to construct a signed 16-bit offset, where the offset is calculated to be (branchbyte1 << 8) | branchbyte2.

因此,偏移量被认为是一个有符号 16位值。但是,已签名 16位值的最大值为32767,而不是32768.

So the offset is said to be a signed 16 bit value. However, the maximum value that a signed 16 bit value can hold is 32767, and not 32768.

生成的类文件似乎仍然是有效,可以正常执行。

The resulting class file still seems to be valid, and can be executed normally.

我看过字节码检查OpenJDK ,并且似乎这只是有效的,因为括号是错放:

I had a look at the bytecode checking in the OpenJDK, and it seems (to me) that this is only valid due to the parentheses being misplaced:

int jump = (((signed char)(code[offset+1])) << 8) + code[offset+2];

它会将第一个字节转换为 signed char 然后,它将应用移位,并添加第二个字节。我希望它是

It will cast the first byte to signed char. Then it will apply the shift, and add the second byte. I would have expected it to be

int jump = (((signed char)(code[offset+1]) << 8)) + code[offset+2];

或甚至

int jump = (signed char)((code[offset+1]) << 8) + code[offset+2]);

但我不熟悉类型升级和可能的编译器特定的移位签名和未签名的警告类型,所以我不知道这个转换后面是否有更深的意义...

but I'm not familiar with the type promotions and possible compiler-specific caveats of shifting signed and unsigned types, so I'm not sure whether there is a deeper meaning behind this cast...

32768的跳转偏移是否符合规范?并且OpenJDK中的跳跃计算代码在这方面是否有意义?

So does a jump offset of 32768 comply to the specification? And does the jump computation code in the OpenJDK make any sense in this regard?

推荐答案

if_icmpge 是一个偏移量,但javap将跳转目标显示为绝对位置。也就是说,javap应该在 32768:而不是 32770:显示 getstatic c $ c>(即,2 + 32768)。

The argument to if_icmpge is an offset, but javap shows the jump target as an absolute position. That is, javap should show a getstatic at 32768: and not 32770: (i.e., 2 + 32768).

这篇关于如何使JVM跳转指令的偏移量为32768?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆