10

I'm trying to understand java byte code. I started with simple example:

public class Test
{
    public static void main(String args[])
    {
        System.out.println(2 + 1);
    }
}

I compiled this class:

javac Test.java

And then I tried to a javap on the .class like this:

javap -c Test

which gave me this:

Compiled from "Test.java"
public class Test {
  public Test();
    Code:
       0: aload_0       
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return        

  public static void main(java.lang.String[]);
    Code:
       0: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
       3: iconst_1      
       4: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
       7: return        
}

I could able to make sense out of it, apart from this line:

public static void main(java.lang.String[]);
. . . 
3: iconst_1    
. . .

looking at my source and this byte code, looks like javac already done the operation of addition for this statement:

2+1

and asking jvm to return that constant.

Can some one correct me if my understanding is wrong? Does javac performs the operation on compilation for +,-,* etc before it actually runs on the jvm? If so how?

batman
  • 3,565
  • 5
  • 20
  • 41

1 Answers1

25

2 + 1 is a compile-time constant expression. The compiler itself replaces it by 3 in the byte-code.

See the Java Language Specification, which says:

Some expressions have a value that can be determined at compile time. These are constant expressions.

See this other chapter for what constitutes a constant expression

A constant expression is an expression denoting a value of primitive type or a String that does not complete abruptly and is composed using only the following:

  • Literals of primitive type and literals of type String [...]
  • The additive operators + and - [...]
Community
  • 1
  • 1
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • So all constant expression is being resolved by compiler? – batman Aug 16 '15 at 11:49
  • 6
    @batman yes, but notice that `1 + 2 + i` and `i + 1 + 2` will be compiled as `3 + i` and `i + 1 + 2`. It happens because of order of operation which in first case is `(1 + 2) + i` so `(1+2)` can be optimized by compiler, but in case of `(i+1) + 2` in `(i + 1)` compiler can't know value of `i` at compilation time, so it will not optimize your code. – Pshemo Aug 16 '15 at 11:54
  • 1
    @Pshemo: Thats an bit of interesting info, on how an parenthesis helps the compiler optimisation. Thanks! – batman Aug 16 '15 at 11:57
  • Another practical usage is to define long strings, like a SQL query, on multiple lines for example. Or a duration like ONE_DAY_IN_MILLIS = 24L * 60L * 60L * 1000L. – JB Nizet Aug 16 '15 at 11:59
  • 2
    The compiler doesn't _have_ to optimize constant expressions, it's just encouraged to and does in practice. – Antimony Aug 16 '15 at 17:15
  • @Pshemo: In particular, while `i+1+2 == i+3` is, in fact, always true for integers, it's *not* always true for floating point numbers. For [a counterexample](http://ideone.com/WTs4HJ), try `double i = 1e16;`. – Ilmari Karonen Aug 16 '15 at 21:41
  • The only question that remains is why in the OPs environment `2+1` is evaluated to `1`… – Holger Aug 18 '15 at 15:03