Generated constructor returns from line number of other method

Eirik Bjørsnøs eirbjo at gmail.com
Wed Oct 22 06:31:24 UTC 2014


If it's even more odd that rather odd, might we even call it a bug? :-)

I noticed that javac also generates a class
WeirdConstructorLinenumber$1 containing a <clinit> which initialises
an int[] switch map:

class no.kantega.labs.revoc.demo.WeirdConstructorLinenumber$1 {
  static final int[] $SwitchMap$java$math$RoundingMode;

  static {};
    Code:
       0: invokestatic  #1                  // Method
java/math/RoundingMode.values:()[Ljava/math/RoundingMode;
       3: arraylength
       4: newarray       int
       6: putstatic     #2                  // Field
$SwitchMap$java$math$RoundingMode:[I
       9: return
    LineNumberTable:
      line 8: 0
}

Looks like for some reason the line number for the <clinit> "leaks"
over to the <init> of the enclosing class.

I first noticed this issue when working on a code coverage tool. For
performance reasons, the tool instruments line number instructions not
by their actual line numbers, but with the count of the first time a
line number occurs in the byte code for that class. The odd line
number in <init> shifted the line count by one which caused line
counts for a method to spill over to the next method in the class.

I imagine other source-aware tools such as code coverage tools, static
analysis tools or even debuggers might be affected by this.

Eirik.



On Wed, Oct 22, 2014 at 12:52 AM, Alex Buckley <alex.buckley at oracle.com> wrote:
>
> It's rather odd that an <init> method corresponding to a default constructor has a LineNumberTable attribute in the first place. After all, the default constructor doesn't correspond to any lines of code in the original source file.
>
> The fact that <init>'s LineNumberTable attribute changes based on the body of another method is even more odd.
>
> Alex
>
>
> On 10/21/2014 3:19 PM, Eirik Bjørsnøs wrote:
>>
>> Hi,
>>
>> Given a class containing a method switching on an enum, like this:
>>
>> 1:  public class WeirdConstructorLinenumber
>> 2:  {
>> 3:     public void consider(java.math.RoundingMode mode) {
>> 4:         switch ( mode ) {}
>> 5:     }
>> 6:  }
>>
>> javac generates a default constructor as expected.
>>
>> But the generated constructor returns from line 4 (which really belongs
>> to the "consider" method).
>>
>> I could only make this happen by having my consider method switc on an
>> enum. If I remove the switch or switch on something different, like an
>> int, the constructor is generated with a single line and returns at line
>> 1 as expected.
>>
>> Could this be a javac bug? Or is there something I'm just completely
>> missing?
>>
>> $ javac WeirdConstructorLinenumber.java
>> $ javap -c -l -classpath . WeirdConstructorLinenumber
>> Compiled from "WeirdConstructorLinenumber.java"
>> public class WeirdConstructorLinenumber {
>>    public WeirdConstructorLinenumber();
>>      Code:
>>         0: aload_0
>>         1: invokespecial #1                  // Method
>> java/lang/Object."<init>":()V
>>         4: return
>>      LineNumberTable:
>>        line 1: 0
>>        line 4: 4
>>
>>     [...]
>> }
>>
>>
>> Thanks,
>> Eirik Bjørsnøs
>>


More information about the compiler-dev mailing list