Felix Crazzolara
Felix Crazzolara

Reputation: 732

How does java optimisation? Example code

Consider this small class:

public class Example {
  public int plus(int a){
    int b;
    b = 1;
    return b+a;
  }
}

javap says:

public int plus(int);
  descriptor: (I)I
  flags: ACC_PUBLIC
  Code:
    stack=2, locals=3, args_size=2
     0: iconst_1
     1: istore_2
     2: iload_2
     3: iload_1
     4: iadd
     5: ireturn
  LineNumberTable:
    line 4: 0
    line 5: 2

I don't understand why we need line 1&2?

I heard that the Java Runtime environment counts function calls and compiles functions if they exceed a certain number of calls.

Does that mean that the Java compiler leaves all optimisation to the byte code compiler? E.g. Java programs start slow and become faster by time?

Please explain!

Upvotes: 1

Views: 185

Answers (1)

Stephen C
Stephen C

Reputation: 719679

First of all, you are looking at the output of the bytecode compiler. Typical Java bytecode compilers do very little optimization. The heavy-weight optimization is done by the JIT compiler ... at runtime.

So what you see displayed by javap -c is unoptimized bytecodes.

I don't understand why we need line 1&2?

You are looking at unoptimized bytecodes. The first 2 instructions assign 1 to the local variable b. We can see that the local variable could easily be optimized away. However the bytecode compler (javac) doesn't bother.

I heard that the Java Runtime environment counts function calls and compiles functions if they exceed a certain number of calls.

That's how a typical Hotspot JVM works.

Does that mean that the Java compiler leaves all optimisation to the byte code compiler?

No. It is the JIT compiler that does the runtime compilation and the associated optimization.

The bytecode compiler compiles Java source code to bytecodes. The JIT compiler compiles bytecodes to native code ... at runtime.

E.g. Java programs start slow and become faster by time?

That is correct. The initial bytecode interpretation phase and the JIT compilation are part of what is referred to as "JVM warmup".


(As requested ...)

The reasons that the bytecode compiler doesn't optimize include:

  • because the JIT compiler does optimize (so it would be wasted effort),
  • because optimizing the bytecodes could make it harder to optimize in the JIT compiler ("clever" code is harder to optimize than simple code), and
  • because non-optimized byte codes make it easier for a profiler or debugger to relate code back to source code lines.

And the reasons the the JIT compiler does the optimization include:

  • because it needs to be done in the step that generates native code to achieve best results,
  • because it is platform dependent (e.g. the optimal code depends on the target instruction set, and potentially on things like memory cache sizes, number of cores and so on), and
  • because it allow you to optimize based on the observed behavior of the code as it is executing (e.g. improved branch prediction).

Finally, JIT compilation fits in well with Java's late binding model.

Upvotes: 3

Related Questions