LocalVariableTable属性、LineNumberTable属性

巴海和 2013-08-22

为什么LocalVariableTable属性中local_variable_info项目里start_pc是从1开始的,为啥不是从0开始呢?难道是为了与length配合吗?而LineNumberTable属性中line_number_info项目里start_pc却是从0开始?

SourceFile属性与方法表、字段表平级的一项属性吗?如果是,除此之外还有哪些平级的属性?求指导!

Offset      0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F

00000000   CA FE BA BE 00 00 00 32  00 2B 07 00 02 01 00 0C   漱壕   2 +      
00000010   65 78 61 6D 70 6C 65 2F  43 61 73 65 07 00 04 01   example/Case    
00000020   00 10 6A 61 76 61 2F 6C  61 6E 67 2F 4F 62 6A 65     java/lang/Obje
00000030   63 74 01 00 07 63 6F 6E  74 65 6E 74 01 00 12 4C   ct   content   L
00000040   6A 61 76 61 2F 6C 61 6E  67 2F 53 74 72 69 6E 67   java/lang/String
00000050   3B 01 00 06 3C 69 6E 69  74 3E 01 00 15 28 4C 6A   ;   <init>   (Lj
00000060   61 76 61 2F 6C 61 6E 67  2F 53 74 72 69 6E 67 3B   ava/lang/String;
00000070   29 56 01 00 04 43 6F 64  65 0A 00 03 00 0B 0C 00   )V   Code       
00000080   07 00 0C 01 00 03 28 29  56 09 00 01 00 0E 0C 00         ()V       
00000090   05 00 06 01 00 0F 4C 69  6E 65 4E 75 6D 62 65 72         LineNumber
000000A0   54 61 62 6C 65 01 00 12  4C 6F 63 61 6C 56 61 72   Table   LocalVar
000000B0   69 61 62 6C 65 54 61 62  6C 65 01 00 04 74 68 69   iableTable   thi
000000C0   73 01 00 0E 4C 65 78 61  6D 70 6C 65 2F 43 61 73   s   Lexample/Cas
000000D0   65 3B 01 00 05 70 72 69  6E 74 09 00 15 00 17 07   e;   print      
000000E0   00 16 01 00 10 6A 61 76  61 2F 6C 61 6E 67 2F 53        java/lang/S
000000F0   79 73 74 65 6D 0C 00 18  00 19 01 00 03 6F 75 74   ystem        out
00000100   01 00 15 4C 6A 61 76 61  2F 69 6F 2F 50 72 69 6E      Ljava/io/Prin
00000110   74 53 74 72 65 61 6D 3B  0A 00 1B 00 1D 07 00 1C   tStream;        
00000120   01 00 13 6A 61 76 61 2F  69 6F 2F 50 72 69 6E 74      java/io/Print
00000130   53 74 72 65 61 6D 0C 00  1E 00 08 01 00 07 70 72   Stream        pr
00000140   69 6E 74 6C 6E 01 00 04  6D 61 69 6E 01 00 16 28   intln   main   (
00000150   5B 4C 6A 61 76 61 2F 6C  61 6E 67 2F 53 74 72 69   [Ljava/lang/Stri
00000160   6E 67 3B 29 56 08 00 22  01 00 0E 48 65 6C 6C 6F   ng;)V  "   Hello
00000170   20 57 69 6E 64 6F 77 73  21 0A 00 01 00 24 0C 00    Windows!    $  
00000180   07 00 08 0A 00 01 00 26  0C 00 13 00 0C 01 00 04          &        
00000190   61 72 67 73 01 00 13 5B  4C 6A 61 76 61 2F 6C 61   args   [Ljava/la
000001A0   6E 67 2F 53 74 72 69 6E  67 3B 01 00 0A 53 6F 75   ng/String;   Sou
000001B0   72 63 65 46 69 6C 65 01  00 09 43 61 73 65 2E 6A   rceFile   Case.j
000001C0   61 76 61 00 21 00 01 00  03 00 00 00 01 00 02 00   ava !           
000001D0   05 00 06 00 00 00 03 00  01 00 07 00 08 00 01 00                   
000001E0   09 00 00 00 46 00 02 00  02 00 00 00 0A 2A B7 00       F        *?
000001F0   0A 2A 2B B5 00 0D B1 00  00 00 02 00 0F 00 00 00    *+? ?        
00000200   0E 00 03 00 00 00 07 00  04 00 08 00 09 00 09 00                   
00000210   10 00 00 00 16 00 02 00  00 00 0A 00 11 00 12 00                   
00000220   00 00 00 00 0A 00 05 00  06 00 01 00 01 00 13 00                   
00000230   0C 00 01 00 09 00 00 00  39 00 02 00 01 00 00 00           9       
00000240   0B B2 00 14 2A B4 00 0D  B6 00 1A B1 00 00 00 02    ? *? ? ?   
00000250   00 0F 00 00 00 0A 00 02  00 00 00 0C 00 0A 00 0D                   
00000260   00 10 00 00 00 0C 00 01  00 00 00 0B 00 11 00 12                   
00000270   00 00 00 09 00 1F 00 20  00 01 00 09 00 00 00 3B                  ;
00000280   00 03 00 01 00 00 00 0D  BB 00 01 59 12 21 B7 00           ? Y !?
00000290   23 B6 00 25 B1 00 00 00  02 00 0F 00 00 00 0A 00   #?%?          
000002A0   02 00 00 00 10 00 0C 00  11 00 10 00 00 00 0C 00                   
000002B0   01 00 00 00 0D 00 27 00  28 00 00 00 01 00 29 00         ' (     ) 
000002C0   00 00 02 00 2A                                         *

 

 

RednaxelaFX 2013-08-22
楼主问题的答案基本上在这里都说得很清楚:http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7

您的Class文件内容是这样的:
Compiled from "Case.java"
public class example.Case extends java.lang.Object
  SourceFile: "Case.java"
  minor version: 0
  major version: 50
  Constant pool:
const #1 = class	#2;	//  example/Case
const #2 = Asciz	example/Case;
const #3 = class	#4;	//  java/lang/Object
const #4 = Asciz	java/lang/Object;
const #5 = Asciz	content;
const #6 = Asciz	Ljava/lang/String;;
const #7 = Asciz	<init>;
const #8 = Asciz	(Ljava/lang/String;)V;
const #9 = Asciz	Code;
const #10 = Method	#3.#11;	//  java/lang/Object."<init>":()V
const #11 = NameAndType	#7:#12;//  "<init>":()V
const #12 = Asciz	()V;
const #13 = Field	#1.#14;	//  example/Case.content:Ljava/lang/String;
const #14 = NameAndType	#5:#6;//  content:Ljava/lang/String;
const #15 = Asciz	LineNumberTable;
const #16 = Asciz	LocalVariableTable;
const #17 = Asciz	this;
const #18 = Asciz	Lexample/Case;;
const #19 = Asciz	print;
const #20 = Field	#21.#23;	//  java/lang/System.out:Ljava/io/PrintStream;
const #21 = class	#22;	//  java/lang/System
const #22 = Asciz	java/lang/System;
const #23 = NameAndType	#24:#25;//  out:Ljava/io/PrintStream;
const #24 = Asciz	out;
const #25 = Asciz	Ljava/io/PrintStream;;
const #26 = Method	#27.#29;	//  java/io/PrintStream.println:(Ljava/lang/String;)V
const #27 = class	#28;	//  java/io/PrintStream
const #28 = Asciz	java/io/PrintStream;
const #29 = NameAndType	#30:#8;//  println:(Ljava/lang/String;)V
const #30 = Asciz	println;
const #31 = Asciz	main;
const #32 = Asciz	([Ljava/lang/String;)V;
const #33 = String	#34;	//  Hello Windows!
const #34 = Asciz	Hello Windows!;
const #35 = Method	#1.#36;	//  example/Case."<init>":(Ljava/lang/String;)V
const #36 = NameAndType	#7:#8;//  "<init>":(Ljava/lang/String;)V
const #37 = Method	#1.#38;	//  example/Case.print:()V
const #38 = NameAndType	#19:#12;//  print:()V
const #39 = Asciz	args;
const #40 = Asciz	[Ljava/lang/String;;
const #41 = Asciz	SourceFile;
const #42 = Asciz	Case.java;

{
private java.lang.String content;

public example.Case(java.lang.String);
  Code:
   Stack=2, Locals=2, Args_size=2
   0:	aload_0
   1:	invokespecial	#10; //Method java/lang/Object."<init>":()V
   4:	aload_0
   5:	aload_1
   6:	putfield	#13; //Field content:Ljava/lang/String;
   9:	return
  LineNumberTable: 
   line 7: 0
   line 8: 4
   line 9: 9

  LocalVariableTable: 
   Start  Length  Slot  Name   Signature
   0      10      0    this       Lexample/Case;
   0      10      1    content       Ljava/lang/String;


public void print();
  Code:
   Stack=2, Locals=1, Args_size=1
   0:	getstatic	#20; //Field java/lang/System.out:Ljava/io/PrintStream;
   3:	aload_0
   4:	getfield	#13; //Field content:Ljava/lang/String;
   7:	invokevirtual	#26; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   10:	return
  LineNumberTable: 
   line 12: 0
   line 13: 10

  LocalVariableTable: 
   Start  Length  Slot  Name   Signature
   0      11      0    this       Lexample/Case;


public static void main(java.lang.String[]);
  Code:
   Stack=3, Locals=1, Args_size=1
   0:	new	#1; //class example/Case
   3:	dup
   4:	ldc	#33; //String Hello Windows!
   6:	invokespecial	#35; //Method "<init>":(Ljava/lang/String;)V
   9:	invokevirtual	#37; //Method print:()V
   12:	return
  LineNumberTable: 
   line 16: 0
   line 17: 12

  LocalVariableTable: 
   Start  Length  Slot  Name   Signature
   0      13      0    args       [Ljava/lang/String;


}


您给的例子里没有LocalVariableTable的项的start_pc是1开始啊。

但如果有类似这样的代码:
public static void foo(int i) {
  int x = i;
  // ...
}

那么x的start_pc就会是1,因为要等到赋值完成的时候它才真的进入了作用域。
形象的说,如果你要写int x = x;就不行,x在声明完成之前不能出现在赋值符号的右边,对吧。
那么对应回字节码,
0: iload_0
1: istore_1 <- 这个时候x才得到赋值,所以这个地方开始它才进入作用域,所以它的start_pc是从1开始而不是从0开始。
Global site tag (gtag.js) - Google Analytics