When the Java file is a interface, such as TestInterface.java
:
public interface TestInterface {
void method(String parameterName);
}
I compile with javac -g TestInterface.java
and then disassemble with javap -v TestInterface
, the output is as follows:
Classfile /private/tmp/TestInterface.class
Last modified Mar 17, 2022; size 148 bytes
MD5 checksum da2f58afc0eaf77badc94c90de385198
Compiled from "TestInterface.java"
public interface TestInterface
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_INTERFACE, ACC_ABSTRACT
Constant pool:
#1 = Class #7 // TestInterface
#2 = Class #8 // java/lang/Object
#3 = Utf8 method
#4 = Utf8 (Ljava/lang/String;)V
#5 = Utf8 SourceFile
#6 = Utf8 TestInterface.java
#7 = Utf8 TestInterface
#8 = Utf8 java/lang/Object
{
public abstract void method(java.lang.String);
descriptor: (Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_ABSTRACT
}
SourceFile: "TestInterface.java"
And when the Java file is a class, such as TestClass.java
:
public class TestClass {
public void method(String parameterName) {
}
}
Compile with javac -g TestClass.java
and then disassemble with javap -v TestClass
, the output is as follows:
Classfile /private/tmp/TestClass.class
Last modified Mar 17, 2022; size 389 bytes
MD5 checksum 8e124ecce6632ad6e1a5bb45888a3168
Compiled from "TestClass.java"
public class TestClass
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #3.#17 // java/lang/Object."<init>":()V
#2 = Class #18 // TestClass
#3 = Class #19 // java/lang/Object
#4 = Utf8 <init>
#5 = Utf8 ()V
#6 = Utf8 Code
#7 = Utf8 LineNumberTable
#8 = Utf8 LocalVariableTable
#9 = Utf8 this
#10 = Utf8 LTestClass;
#11 = Utf8 method
#12 = Utf8 (Ljava/lang/String;)V
#13 = Utf8 parameterName
#14 = Utf8 Ljava/lang/String;
#15 = Utf8 SourceFile
#16 = Utf8 TestClass.java
#17 = NameAndType #4:#5 // "<init>":()V
#18 = Utf8 TestClass
#19 = Utf8 java/lang/Object
{
public TestClass();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
LineNumberTable:
line 1: 0
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this LTestClass;
public void method(java.lang.String);
descriptor: (Ljava/lang/String;)V
flags: ACC_PUBLIC
Code:
stack=0, locals=2, args_size=2
0: return
LineNumberTable:
line 5: 0
LocalVariableTable:
Start Length Slot Name Signature
0 1 0 this LTestClass;
0 1 1 parameterName Ljava/lang/String;
}
SourceFile: "TestClass.java"
Why is LocalVariableTable
not included in the class file of the interface?
JDK version: 1.8.0_311
Because that's not how the class file structure works.
According to the JVM spec, the LocalVariableTable
is part of a Code
attribute:
The
LocalVariableTable
attribute is an optional variable-length attribute in theattributes
table of aCode
attribute (§4.7.3). It may be used by debuggers to determine the value of a given local variable during the execution of a method.
However, interface methods are abstract (i.e. having the flag ACC_ABSTRACT
), so they can't have Code
attributes in the first place (§4.7.3).
The
Code
attribute is a variable-length attribute in theattributes
table of amethod_info
structure (§4.6). ACode
attribute contains the Java Virtual Machine instructions and auxiliary information for a method [...]If the method is either
native
orabstract
, and is not a class or interface initialization method, then itsmethod_info
structure must not have aCode
attribute in itsattributes
table.
So it is not possible for javac
to generate a LocalVariableTable
for you abstract interface method, even if it wanted to, because that would not produce a correct class file.
Another way to think about it is that the parameter of the method doesn't actually "exist" until you concretely implement it. After all, an abstract method is supposed to just be a "requirement" without "implementations". I don't really see why you would expect there to be local variables, since they are implementation details.