Java字节码缺少局部变量表

0 java jvm bytecode

在查看JDK1.7的字节码时,我发现javax.swing.event.EventListenerListrt.jar中的一些Java类(例如,)的字节码不包含局部变量表。例如,我使用javap -v -p -l EventListenerList.class命令并获得了add方法的字节码,例如:

public synchronized <T extends java.util.EventListener> void add(java.lang.Class<T>, T);
描述符:(Ljava/lang/Class;Ljava/util/EventListener;)V
标志:ACC_PUBLIC、ACC_SYNCHRONIZED
代码:
  堆栈=5,本地人=5,args_size=3
     0:aload_2
     1: ifnonnull 5
     4:返回
     5:aload_1
     6:aload_2
     7: invokevirtual #133 // 方法 java/lang/Class.isInstance:(Ljava/lang/Object;)Z
    ...
   116:加载_0
   117:加载 4
   119: putfield #128 // 字段 listenerList:[Ljava/lang/Object;
   122:返回
  StackMapTable:number_of_entries = 4
    frame_type = 5 /* 相同 */
    frame_type = 43 /* 相同 */
    frame_type = 28 /* 相同 */
    frame_type = 43 /* 相同 */
  行号表:
    第 179 行:0
    第 183 行:4
    第 185 行:5
    第 186 行:13
    ...
    第 200 行:109
    第 202 行:116
    第 204 行:122
签名:#85 // <T::Ljava/util/EventListener;>(Ljava/lang/Class<TT;>;TT;)V

我们可以看到该方法有两个局部变量,但是JDK字节码没有显示局部变量表。我的问题是:

  1. 为什么验证没有显式局部变量表的字节码?
  2. JVM在运行这样的字节码时如何获取启动PC、名称和签名?

Ant*_*ony 5

局部变量表仅用于调试目的 - 它对字节码的执行没有任何直接影响。您可以告诉 javac 通过传递-g:none.

至于第二个问题,没有。JVM 不关心您在源代码级别声明了哪些变量——它所看到的只是字节码中传递的值。

  • 请注意,默认设置 (`-g`) 是包含行号和源文件名称,但不包含局部变量表。这就是 JDK 类的编译方式。指定 `-g:none` 甚至会跳过行号(至少一些 JRE 带有以这种方式编译的类)。 (2认同)