转到 Java 字节码中的

2022-09-02 03:24:02

所以有一天,当我在查看Java字节码的维基百科页面时,我遇到了这个例子:

请考虑以下 Java 代码:

  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);
  }

Java 编译器可能会将上面的 Java 代码转换为字节代码,如下所示,假设上述代码被放在一个方法中:

  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

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


答案 1

Java 结构化编程功能(如循环 (/ ))在字节码级别使用条件分支 () 和无条件跳转 () 指令实现。forwhileIF..GOTO

break或者对于外部循环,在结构化编程中也被认为是足够有用和合法的,Java语言具有这些功能(中断/继续标记)。continue

在 JVM/字节码级别,这些也是使用 实现的。GOTO

看:


答案 2

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

在高级代码中使用跳转是一种不好的做法,就像在C中一样。因此,在Java中不允许这样做。goto

Edsger W. Dijkstra关于goto的原始论文

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


推荐