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