Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is javap missing some line numbers?

If I compile the following source code:

1.  public class Example {
2.    public boolean foo(boolean a, boolean b, char ch) {
3.      if (a && Character.isLetter(ch)
4.            || b && Character.isDigit(ch)
5.            || !a && !b) {
6.        return true;
7.      }
8.      return false;
9.    }
10. }

with Java-7 (either OpenJDK or Oracle) I get the following LineNumberTable:

line 3: 0
line 6: 30
line 8: 32

However, compiling the same source code with Java 8 (either OpenJDK or Oracle) I get another LineNumberTable:

line 3: 0
line 4: 16
line 6: 30
line 8: 32

Why does the LineNumberTable returned by Java 7 not include lines 4 and 5?

And why does the LineNumberTable returned by Java 8 not include line 5?

like image 248
josecampos Avatar asked Sep 26 '22 15:09

josecampos


1 Answers

Well, it isn’t exactly specified, how many hints compilers should include. It’s always a trade-off between usefulness and resulting code size. In the worst case, you would have a several byte length information for each single-byte instruction. Also, certain language constructs may generate instructions spread over different byte code locations, whereas others do not not map to byte code instructions at all.

The strategy of previous javac implementations was simple. Unlike Eclipse, it doesn’t generate line number information for expressions, but only for statements. So a single statement may span multiple source code lines but its entire code gets associated with the statement’s first line only.

Apparently, this strategy has been changed to make an exception to this rule when there are embedded method invocations. So for method invocations, there will be a line number information, but not for other expressions.

You may verify this by playing around with multi-line statements deliberately adding or removing nested invocations. E.g., the following code

static int test(int a, int b, int c, int d) {
    return
            a
           +b
           +c
           +d;
}

will report only a single line number, the one bearing the return keyword. Now change the code to

static int test(int a, int b, int c, int d) {
    return
            a
           +b
           +c+test(a,b,c,d)
           +d;
}

and the line number table will have two entries, the one of the return keyword and the one of the nested method invocation. You may move the invocation to a different line or even adding another invocation, e.g.

static int test(int a, int b, int c, int d) {
    return
            a
           +b+test(a,b,c,d)
           +c
           +d+test(a,b,c,d);
}

and the line number table will support my guess about javac’s new strategy.

like image 167
Holger Avatar answered Oct 12 '22 12:10

Holger