Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does a Java class compile differently with a blank line?

People also ask

Will a blank Java class file compile?

since your java file contained none, the compiler justly didn't generate any class files. Show activity on this post. If you would've declared the class, (e.g., public class test{ } ), it would compile and create test. class file.

What is the function of the following compiler option G None?

Java compiling - Use javac -g:none to reduce Java class file size. to compile your Java class files when you're ready to deploy your application. This command does not put any debugging information in your . class files, and seems to reduce the size of these files by 10-16%.


Basically, line numbers are kept for debugging, so if you change your source code the way you did, your method starts at a different line and the compiled class reflects the difference.


You can see the change by using javap -v which will output verbose information. Like other already mentioned the difference will be in line numbers:

$ javap -v HelloWorld.class > with-line.txt
$ javap -v HelloWorld.class > no-line.txt
$ diff -C 1 no-line.txt with-line.txt
*** no-line.txt 2018-10-03 11:43:32.719400000 +0100
--- with-line.txt       2018-10-03 11:43:04.378500000 +0100
***************
*** 2,4 ****
    Last modified 03-Oct-2018; size 373 bytes
!   MD5 checksum 058baea07fb787bdd81c3fb3f9c586bc
    Compiled from "HelloWorld.java"
--- 2,4 ----
    Last modified 03-Oct-2018; size 373 bytes
!   MD5 checksum 435dbce605c21f84dda48de1a76e961f
    Compiled from "HelloWorld.java"
***************
*** 50,52 ****
        LineNumberTable:
!         line 3: 0
        LocalVariableTable:
--- 50,52 ----
        LineNumberTable:
!         line 4: 0
        LocalVariableTable:

More precisely the class file differs in the LineNumberTable section:

The LineNumberTable attribute is an optional variable-length attribute in the attributes table of a Code attribute (§4.7.3). It may be used by debuggers to determine which part of the code array corresponds to a given line number in the original source file.

If multiple LineNumberTable attributes are present in the attributes table of a Code attribute, then they may appear in any order.

There may be more than one LineNumberTable attribute per line of a source file in the attributes table of a Code attribute. That is, LineNumberTable attributes may together represent a given line of a source file, and need not be one-to-one with source lines.


The assumption that "Java ignores blank lines" is wrong. Here is a code snippet that behaves differently depending on the number of empty lines before the method main:

class NewlineDependent {

  public static void main(String[] args) {
    int i = Thread.currentThread().getStackTrace()[1].getLineNumber();
    System.out.println((new String[]{"foo", "bar"})[((i % 2) + 2) % 2]);
  }
}

If there are no empty lines before main, it prints "foo", but with one empty line before main, it prints "bar".

Since the runtime behavior is different, the .class files must be different, regardless of any timestamps or other metadata.

This holds for every language that has access to the stack frames with line numbers, not only for Java.

Note: if it's compiled with -g:none (without any debugging information), then the line numbers will not be included, getLineNumber() always returns -1, and the program always prints "bar", regardless of the number of line breaks.


As well as any line number details for debugging, your manifest may also store the build time and date. This will naturally be different every time you compile.