Could a Java compiler reorder function calls?

2020-08-17 06:14发布

问题:

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

回答1:

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.



回答2:

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.