Java字节码中的goto

Java字节码中的goto,java,goto,Java,Goto,前几天,当我在维基百科上查看Java字节码页面时,我遇到了这个例子: 考虑以下Java代码: 我注意到,goto这个小单词出现了好几次,在检查规范后,它是有效的我的问题是为什么?GOTO在Java中是一个保留但不可用的关键字,所以为什么在编写和编译Java代码时,它似乎会随着GOTO重新编译到Java中。我想知道这只是在较低级别的编程中一直采用的方式,还是因为JVM可以更有效地使用goto这个词。最后,我很好奇为什么goto被认为是如此糟糕的做法,以至于它在java代码中被禁止,但在编译时却被直

前几天,当我在维基百科上查看Java字节码页面时,我遇到了这个例子:

考虑以下Java代码:


我注意到,goto这个小单词出现了好几次,在检查规范后,它是有效的我的问题是为什么?GOTO在Java中是一个保留但不可用的关键字,所以为什么在编写和编译Java代码时,它似乎会随着GOTO重新编译到Java中。我想知道这只是在较低级别的编程中一直采用的方式,还是因为JVM可以更有效地使用goto这个词。最后,我很好奇为什么goto被认为是如此糟糕的做法,以至于它在java代码中被禁止,但在编译时却被直接放回代码中。

您看到的是JVM与机器代码的等价物。Java中是否允许
goto
与字节码中是否允许无关,正如JVM字节码中不允许使用指针一样,但JVM肯定会将字节码编译或解释为使用指针的机器代码。

Java结构化编程功能,如循环(
for
/
while
)在字节码级别通过条件分支(
IF..
)和无条件跳转(
GOTO
)指令实现

break
continue
到外部循环在结构化编程中也被认为是非常有用和合法的,Java语言具有这些特性(break/continue-to-label)

在JVM/字节码级别,它们也通过
GOTO
实现

见:


字节码是虚拟机的某种汇编语言。机器语言中的跳转指令非常常见。goto是一种无条件跳转指令

Java编译器将方法体中几乎所有的控制流语句转换为goto指令


goto关键字可能在Java中被保留,以保留将其添加到更高版本的选项,以防它的存在变得至关重要。从机器的角度来看,goto实际上没有什么问题。它的名声不好,因为它允许编写人类很难读懂的代码。Java语言允许您使用带标签的break和continue来代替goto。

您应该区分语言关键字
goto
和字节码或汇编指令
goto

在高级代码中使用
goto
跳转是不好的做法,如在C中。因此,在Java中是不允许的


在编译代码中,使用无条件跳转指令
goto
是完全可以的。它是由编译器放在那里的,它不会忘记跳转代码的含义,包括初始化数据、释放内存等。

字节码不是Java,其他语言(如Groovy)中的程序可以编译成字节码代码,您可以使用BCEL等工具直接编写字节码。至于goto,您在低级别上不能没有它。

goto
在机器级别上很好,java编译器不编写代码,它只将java源代码转换为字节码

对于编写代码的人来说,这是一个不同的故事,转到指令很难阅读和分析代码在多次转到跳转后变得一团糟。这就是为什么人们应该使用OO概念而不是跳转指令

  • SpaceTrucker(在对标题问题的评论中)提到了Java语言本身和字节码之间的区别。
    goto
    关键字和
    goto
    指令不一样。唯一常见的是名称。对于字节码,它只是一条
    JUMP
    JMP
    )指令
  • 基本上,
    goto
    被认为是编程/编码中的一种不好的做法,因为实现了“spagetti”代码并使代码的可读性变差

  • 编程中的Goto语句是单向语句,其中as函数调用是双向开关,即它将返回到代码的被调用部分

    如果只使用这些字节码,则在其中使用goto。如果允许用户使用goto,则意味着我们可能会以低效的方式使用它(如无条件goto语句),这将永远不会让程序终止

    Jvm非常智能,从不让程序无限运行。

    一般背景信息: 任何微处理器的硬件部分只知道它需要从一个内存地址开始依次执行每一条指令——它甚至不知道在哪个内存地址停止执行指令

    汇编语言是一种从“命令”到“二进制微指令”的非常精简的转换器。“命令”列表根本不包括控制流语句,您所拥有的只是跳转指令(简单跳转或条件跳转),就是这样(好的,有一条指令用于无条件循环和条件循环)

    因此,在高级语言(如C)中可用的控制流语句是使用这些跳转指令实现的,因为没有其他方法来实现它们。C中的
    goto
    被编译成二进制指令,作为一个简单的无条件跳转指令

    Java和JVM的基本原理: 许多不同的硬件架构都有不同的“二进制微指令”标准/格式和不同的指令集。JVM有自己的标准和指令集

    这允许Java编译器始终输出相同的指令,无论可执行文件将在什么硬件体系结构上运行;JVM的工作是将指令从其自身的标准转换为当前机器的标准

    因此,JVM字节码本质上是一个“as”
      outer:
      for (int i = 2; i < 1000; i++) {
          for (int j = 2; j < i; j++) {
              if (i % j == 0)
              continue outer;
         }
         System.out.println (i);
      }
    
      0:   iconst_2
      1:   istore_1
      2:   iload_1
      3:   sipush  1000
      6:   if_icmpge       44
      9:   iconst_2
      10:  istore_2
      11:  iload_2
      12:  iload_1
      13:  if_icmpge       31
      16:  iload_1
      17:  iload_2
      18:  irem
      19:  ifne    25
      22:  goto    38
      25:  iinc    2, 1
      28:  goto    11
      31:  getstatic       #84; //Field java/lang/System.out:Ljava/io/PrintStream;
      34:  iload_1
      35:  invokevirtual   #85; //Method java/io/PrintStream.println:(I)V
      38:  iinc    1, 1
      41:  goto    2
      44:  return