11

I know that java compiler can actually reorder code instructions. But can java reorder function calls?

For example:

...
//these lines may be reordered
a=7;
b=5;
...
//but what about this?
callOne();
callTwo();
Vince
  • 14,470
  • 7
  • 39
  • 84
Tony
  • 459
  • 1
  • 5
  • 18
  • I doubt it. Reordering is only possible when the end results are the same either way. In the case of functions, you could be acting on an interface whose impl may change (strategy, abstract method, etc..). Not to mention monitoring for potential side effects, which I don't believe can be determined at call level. – Vince Apr 20 '18 at 21:34
  • Compilet & the jvm are free to reorder instructions as long they don’t alter the behaviour of the program – nitnamby Apr 20 '18 at 21:35
  • Can I ask what the benefit of reordering the two variable declarations would be? – Sam Orozco Apr 20 '18 at 21:35
  • @VinceEmigh Or it can be a static or final method that can be safely inlined. – shmosel Apr 20 '18 at 21:36
  • 1
    @shmosel But what if those functions modify some external source, and although the program may execute fluently, the external results differ? For example, one function writes header data to a file, then the other function writes the actual content. They both write properly, but now the header data comes before the content. – Vince Apr 20 '18 at 21:42
  • 1
    @VinceEmigh You yourself said *"Reordering is only possible when the **end results are the same** either way"*, so why do you think that doesn't cover *"external results"*? It applies to **all results**. – Andreas Apr 20 '18 at 21:48
  • @Andreas By *end results*, I was talking about the internal state of the program, not state of the external entities (such as a file, or a database as the OP suggested), which I don't believe the compiler could analyze. But I could be completely wrong, as I don't have any sources to back up what I've said. Although I don't believe the compiler accounts for the state of the potentially infinite amount of external entities that may be receiving the data your program outputs. Are you suggesting the compiler monitors for this, and *would* reorder functions if the external results DID match? – Vince Apr 20 '18 at 22:01
  • 2
    @VinceEmigh I'm saying that compiler *knows* it cannot make any guarantees on the effect/results of external actions, so it simply is not *allowed* to rearrange external actions, such as I/O to files, database, servers, etc. It is only allowed to rearrange code if it can *guarantee* that **all** results will be the same. – Andreas Apr 20 '18 at 22:15

2 Answers2

9

If it can determine that doing so would have no effect on the result, then yes. Since it can't, the compiler won't.

JIT can however inline the calls, since it knows if the methods are overridden, and it can then rearrange the code, if it sees fit. Since it can only do so if it can guarantee that result stays the same, why would you even care? You can't see a difference anyway.

Andreas
  • 154,647
  • 11
  • 152
  • 247
  • When JIT cannot say if code may be reordered? Can JIT reorder IO calls? IO calls usually don't affect on program state, but it can affect on DB state. – Tony Apr 20 '18 at 21:43
  • 1
    @Tony Which part of my answer says that "guarantee that result stays the same" is *limited* to program state? Database state is "result" too. If you rearrange IO, then *result* is obviously **not** the same. – Andreas Apr 20 '18 at 21:44
  • Are you suggesting the compiler accounts for the state of external entities, and that it would reorder the functions if the external state matched either way? – Vince Apr 20 '18 at 22:09
  • Can you provide some documentation? – Tony Apr 20 '18 at 22:13
  • 1
    Can you say a particular page? – Tony Apr 20 '18 at 22:19
  • 1
    @Tony Try re-reading wherever you read that *"compiler can actually reorder code instructions"*. – Andreas Apr 20 '18 at 22:27
  • 1
    @Tony - Section 17.4. You need to read *and understand* much of the section to get a handle on what reordering is permitted. – Stephen C Apr 20 '18 at 22:30
  • @Tony JLS Link: [17.4. Memory Model](https://docs.oracle.com/javase/specs/jls/se10/html/jls-17.html#jls-17.4) *(thanks to Stephen for reference)* – Andreas Apr 20 '18 at 22:37
4

For a single-threaded program, reordering of instructions (including method calls) is only permitted if it can be proven that the reordering doesn't affect the results of the computation. This is not stated explicitly1 in the JLS, but it is implicit:

  • The JLS (as an entire document) specifies what a well-formed single-threaded program will do.

  • If a compiler reordered instructions in a program so that it behaved differently to what the spec says, then the compiler would not conform to the JLS.


For a multi-threaded program, Chapter 17.4 Memory Model permits reorderings that might affect the behavior of a program which doesn't synchronize correctly.

The JLS states:

A memory model describes, given a program and an execution trace of that program, whether the execution trace is a legal execution of the program. The Java programming language memory model works by examining each read in an execution trace and checking that the write observed by that read is valid according to certain rules.

The memory model describes possible behaviors of a program. An implementation is free to produce any code it likes, as long as all resulting executions of a program produce a result that can be predicted by the memory model.

This provides a great deal of freedom for the implementor to perform a myriad of code transformations, including the reordering of actions and removal of unnecessary synchronization.

The semantics of the Java programming language allow compilers and microprocessors to perform optimizations that can interact with incorrectly synchronized code in ways that can produce behaviors that seem paradoxical.

It gives examples of this behavior before diving into the technical details of the Java memory model ... for the next 20 or so pages.


For your example, a reordering of those method calls would be permitted if it can be proven that it would make no difference2. Whether that can proven will depend on what the methods do.


1 - Actually, JLS 17.4.7, case 3 could be construed as explicitly forbidding reorderings that change behavior in the single-threaded case. The JMM is ... difficult to understand ... and I don't claim to be sufficiently expert to state categorically what it means in this matter.

2 - ... to any well-formed execution in the sense of JLS 17.4.7.

Community
  • 1
  • 1
Stephen C
  • 698,415
  • 94
  • 811
  • 1,216