21

So the other day when I was looking at the wikipedia page for Java bytecode I came across this example:

Consider the following Java code:

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

A Java compiler might translate the Java code above into byte code as follows, assuming the above was put in a method:

  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

And I notice that little word goto appears a couple of times, which upon checking the JVM specification is valid. My question is why? GOTO is a reserved but unusable keyword in Java, so why when we write and compile java code does it seem to get compiled with goto back into it. I am wondering it this is just the way things have always been done at a lower level of programming, or whether it is because the JVM is trusted to use the goto word more effectively. Ultimately I am curious as to why goto is considered such bad practice that it is prohibited in java code, yet seems to be put straight back into your code when compiled.

Sled
  • 18,541
  • 27
  • 119
  • 168
Levenal
  • 3,796
  • 3
  • 24
  • 29
  • 16
    You think bytecode has bad practices? Wait till you see the JITted native code - full of magic numbers, gotos, reuses of same variable names for different purposes, and same code appearing in multiple places as if it was copypasted. Wait what – Esailija Nov 15 '13 at 08:57
  • 28
    Bytecode and Java are two different languages. So a rule for one of them doesn't necessarily apply to the other. – SpaceTrucker Nov 15 '13 at 08:58
  • 11
    goto is bad for people, but not for smart machines :) – MariuszS Nov 15 '13 at 08:59
  • 2
    Actually @SpaceTrucker 's comment is the best answer for this question. – StarPinkER Nov 22 '13 at 02:23

9 Answers9

15

Java structured programming features such as loops (for/ while) are implemented at the bytecode level with conditional branch (IF..) and unconditional jump (GOTO) instructions.

break or continue to an outer loop are also considered sufficiently useful & legitimate within structured programming, that the Java language has these features (break/ continue to label).

At the JVM/ bytecode level, these are also implemented with GOTO.

See:

Thomas W
  • 13,940
  • 4
  • 58
  • 76
  • 7
    +1 Actually, `break` and `continue` are `goto` statements in disguise with a very specific and limited scope. They are too useful to leave out but limited enough to avoid most of the problems `goto` creates. – Aaron Digulla Nov 15 '13 at 09:13
  • Thanks Aaron, that was initially my point -- that these are the closest Java has, at the language-level, to GOTO. But at the low level, all loops map down to IF(branch) and GOTO. – Thomas W Nov 15 '13 at 09:16
  • 2
    @AaronDigulla "they are implemented as `goto`" -- yes; "they are goto statements in disguise" -- kinda; The point is that they come with contextual constraints and because of that they are easy to read and follow. – Mihai Stancu Nov 15 '13 at 10:22
  • My professor always taught that explicit goto calls in higher level code should be only done under penalty of ridicule by your colleagues. :) Or in other words, 'If you asking yourself if you need to use a goto statement, the answer is always no.' – K.Niemczyk Nov 15 '13 at 16:15
8

You should distinguish between language keyword goto and byte code or assembly instruction goto.

It is bad practice to use goto jumps in high level code, like in C. Therefore it is not allowed in Java.

The original Edsger W. Dijkstra paper on goto.

In compiled code usage of unconditional jump instruction goto is completely OK. It is put in there by compiler and it does not forget about implications of jumping around the code including initialization of data, deallocating memory etc.

Grzegorz Żur
  • 47,257
  • 14
  • 109
  • 105
  • 11
    It is actually recommended to use `goto` in C, because it allows for clean code when handling errors, for example. – Florian Margaine Nov 15 '13 at 10:47
  • 1
    @FlorianMargain Furthermore, where can we download or, more generally, in any manner interact with a program, running on any system, that has some piece of code in it that can be traced back to Dijkstra somewhere in its revision history? It's easy to disparage people's programming practices when all you're writing is a paper. Wikipedia: *Dijkstra eschewed the use of computers in his own work for many decades. Almost all EWDs appearing after 1972 were hand-written. When lecturing, he would write proofs in chalk on a blackboard rather than using overhead foils.* Yeah, tell me how to code! – Kaz Nov 15 '13 at 18:20
  • 1
    @Kaz Maybe he hasn't written any known piece of software (I don't know). But if you have used ALGOL 60, Pascal, C, structured programming or Dijkstra's algorithm, you have built upon his work. – GregT Nov 10 '17 at 08:35
7

General background info:

The hardware part of any microprocessor only knows it needs to successively execute every instruction starting from a memory address -- it doesn't even know at which memory address to stop executing instructions.

Assembly language is a very thin converter from "commands" to "binary microinstructions". The list of "commands" does not include control flow statements at all all you have is jump instructions (simple jumps or conditional jumps), that's it (okay, there is an instruction for unconditional endless loops and for conditional loops).

Because of this the control flow statements which are available in higher languages such as C are implemented using these jump instructions because there is no other way to implement them. As it so happens goto in C is compiled into binary instructions as just a simple unconditional jump instruction.

Java & JVM rationale:

Many different hardware architectures have different standards/formats for "binary microinstructions" and different sets of instructions. The JVM has its own standard and its own set of instructions.

This allows the Java Compiler to always output the same instructions no matter on what hardware architecture the executable will be run; it's the JVM's job to translate an instruction from its own standard into the current machine's standard.

So in essence the JVM bytecode is an "assembly language" for "the java virtual machine". Which means it doesn't have control flow instructions. It has unconditional jump instructions (which happen to be named goto).

break and continue at the lowest level happen to be implemented as a jump (or goto). The point of the matter is that if you use a higher level language you would want to avoid using goto even if it's available (like in C), and would use the more readable control structures.

There are some special cases (in C for ex.) when even programmers who respect all of the "best coding practices" would use a goto for example coroutine implementations.

Some other examples of sacrificing the coding standards for better or more reliable performance is when Kernel developers have architecture specific assembly code (C allows you to write assembly instructions).

Mihai Stancu
  • 15,848
  • 2
  • 33
  • 51
4

Bytecode is some sort of assembly language for the virtual machine. It is very common to have jump instructions in machine language. goto is a unconditional jump instruction.

The Java compiler translates almost all control flow statements inside a method body into goto instructions.

The goto keyword was probably reserved in Java to retain the option to add it to a later version in case it would have turned out that it's existence would have been critical. There is actually nothing wrong with goto from a machine point of view. It has got a bad reputation because it allows to write code that is very hard to read for a human. The Java language allows you to use break and continue with labels as a replacement for goto.

x4u
  • 13,877
  • 6
  • 48
  • 58
2

goto is fine at machine level, java compiler are not writing code, it only converts code from java source to bytecode.

For people writing code this is diffrent story, goto instruction are hard to read and analyze and code is the mess after many goto jumps. This is why people should use OO concepts instead of jump instructions.

MariuszS
  • 30,646
  • 12
  • 114
  • 155
1

You're looking at the JVM's equivalent of machine code. Whether goto is permitted in Java is irrelevant to whether it's permitted in the bytecode, just as pointers aren't permitted in JVM bytecode, but the JVM will certainly compile or interpret the bytecode into machine code that does use pointers.

chrylis -cautiouslyoptimistic-
  • 75,269
  • 21
  • 115
  • 152
0

bytecode isn't Java, programs in other languages, like Groovy, can be compiled into bytecode, you can write bytecode directly using some tools like BCEL. As for goto you cannot go without it at low level.

Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275
0
  1. SpaceTrucker mentioned (in comments to head question) a difference between the Java language itself and bytecode. The goto keyword and goto instruction are not the same. The only common thing is the name. In case of bytecode it is just an instruction of JUMP (JMP);
  2. Basically, goto is thought to be a bad practice in programming/coding, because of realizing the 'spagetti' code and making worse the readability of code.
Nikolay Antipov
  • 920
  • 2
  • 8
  • 17
0

Goto statements in programming are one way statements where as function calls are two way switch that is it will return back to the called section of the code.

To use those only bytecodes use goto in them. In case if user is allowed to use goto means we may use it in a inefficient way (say unconditioned goto statement) which will never let the program to terminate.

Jvm is such intelligent that never let the program run infinitely.

Govan
  • 7,751
  • 5
  • 26
  • 42