Java class文件结构的一个详细分析案例

最近在研究Java的字节码,花了点时间分析了一段十分简单的代码生成的class文件.
首先是代码:

package com.agpalace.article.java.bytecode.chapter1;

/**
 * Created by dengming on 17/3/30.
 */
public class HelloWorld {

    public static void main(String arg[]){
        String helloWorld="Hello, world";
        System.out.println(helloWorld);
    }
}

这个就是Java程序员入门的程序HelloWorld。
使用javap命令,加上-verbose选项反解析得到:

/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/bin/javap -verbose -c com.agpalace.article.java.bytecode.chapter1.HelloWorld
Classfile /Users/dengming/git/JavaBytecode/target/classes/com/agpalace/article/java/bytecode/chapter1/HelloWorld.class
  Last modified 2017-3-30; size 670 bytes
  MD5 checksum 16c016889ca99530664fba1fbebd6aec
  Compiled from "HelloWorld.java"
public class com.agpalace.article.java.bytecode.chapter1.HelloWorld
  minor version: 0
  major version: 49
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #6.#22         // java/lang/Object."<init>":()V
   #2 = String             #23            // Hello, world
   #3 = Fieldref           #24.#25        // java/lang/System.out:Ljava/io/PrintStream;
   #4 = Methodref          #26.#27        // java/io/PrintStream.println:(Ljava/lang/String;)V
   #5 = Class              #28            // com/agpalace/article/java/bytecode/chapter1/HelloWorld
   #6 = Class              #29            // java/lang/Object
   #7 = Utf8               <init>
   #8 = Utf8               ()V
   #9 = Utf8               Code
  #10 = Utf8               LineNumberTable
  #11 = Utf8               LocalVariableTable
  #12 = Utf8               this
  #13 = Utf8               Lcom/agpalace/article/java/bytecode/chapter1/HelloWorld;
  #14 = Utf8               main
  #15 = Utf8               ([Ljava/lang/String;)V
  #16 = Utf8               arg
  #17 = Utf8               [Ljava/lang/String;
  #18 = Utf8               helloword
  #19 = Utf8               Ljava/lang/String;
  #20 = Utf8               SourceFile
  #21 = Utf8               HelloWorld.java
  #22 = NameAndType        #7:#8          // "<init>":()V
  #23 = Utf8               Hello, world
  #24 = Class              #30            // java/lang/System
  #25 = NameAndType        #31:#32        // out:Ljava/io/PrintStream;
  #26 = Class              #33            // java/io/PrintStream
  #27 = NameAndType        #34:#35        // println:(Ljava/lang/String;)V
  #28 = Utf8               com/agpalace/article/java/bytecode/chapter1/HelloWorld
  #29 = Utf8               java/lang/Object
  #30 = Utf8               java/lang/System
  #31 = Utf8               out
  #32 = Utf8               Ljava/io/PrintStream;
  #33 = Utf8               java/io/PrintStream
  #34 = Utf8               println
  #35 = Utf8               (Ljava/lang/String;)V
{
  public com.agpalace.article.java.bytecode.chapter1.HelloWorld();
    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 6: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   Lcom/agpalace/article/java/bytecode/chapter1/HelloWorld;

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=2, args_size=1
         0: ldc           #2                  // String Hello, world
         2: astore_1
         3: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
         6: aload_1
         7: invokevirtual #4                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        10: return
      LineNumberTable:
        line 9: 0
        line 10: 3
        line 11: 10
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      11     0   arg   [Ljava/lang/String;
            3       8     1 helloword   Ljava/lang/String;
}
SourceFile: "HelloWorld.java"

Process finished with exit code 0

用文本编辑器打开class文件,其二进制内容是:

cafe babe 0000 0031 0024 0a00 0600 1608
0017 0900 1800 190a 001a 001b 0700 1c07
001d 0100 063c 696e 6974 3e01 0003 2829
5601 0004 436f 6465 0100 0f4c 696e 654e
756d 6265 7254 6162 6c65 0100 124c 6f63
616c 5661 7269 6162 6c65 5461 626c 6501
0004 7468 6973 0100 384c 636f 6d2f 6167
7061 6c61 6365 2f61 7274 6963 6c65 2f6a
6176 612f 6279 7465 636f 6465 2f63 6861
7074 6572 312f 4865 6c6c 6f57 6f72 6c64
3b01 0004 6d61 696e 0100 1628 5b4c 6a61
7661 2f6c 616e 672f 5374 7269 6e67 3b29
5601 0003 6172 6701 0013 5b4c 6a61 7661
2f6c 616e 672f 5374 7269 6e67 3b01 0009
6865 6c6c 6f77 6f72 6401 0012 4c6a 6176
612f 6c61 6e67 2f53 7472 696e 673b 0100
0a53 6f75 7263 6546 696c 6501 000f 4865
6c6c 6f57 6f72 6c64 2e6a 6176 610c 0007
0008 0100 0c48 656c 6c6f 2c20 776f 726c
6407 001e 0c00 1f00 2007 0021 0c00 2200
2301 0036 636f 6d2f 6167 7061 6c61 6365
2f61 7274 6963 6c65 2f6a 6176 612f 6279
7465 636f 6465 2f63 6861 7074 6572 312f
4865 6c6c 6f57 6f72 6c64 0100 106a 6176
612f 6c61 6e67 2f4f 626a 6563 7401 0010
6a61 7661 2f6c 616e 672f 5379 7374 656d
0100 036f 7574 0100 154c 6a61 7661 2f69
6f2f 5072 696e 7453 7472 6561 6d3b 0100
136a 6176 612f 696f 2f50 7269 6e74 5374
7265 616d 0100 0770 7269 6e74 6c6e 0100
1528 4c6a 6176 612f 6c61 6e67 2f53 7472
696e 673b 2956 0021 0005 0006 0000 0000
0002 0001 0007 0008 0001 0009 0000 002f
0001 0001 0000 0005 2ab7 0001 b100 0000
0200 0a00 0000 0600 0100 0000 0600 0b00
0000 0c00 0100 0000 0500 0c00 0d00 0000
0900 0e00 0f00 0100 0900 0000 4700 0200
0200 0000 0b12 024c b200 032b b600 04b1
0000 0002 000a 0000 000e 0003 0000 0009
0003 000a 000a 000b 000b 0000 0016 0002
0000 000b 0010 0011 0000 0003 0008 0012
0013 0001 0001 0014 0000 0002 0015 

我所解析的内容就是这段二进制文件,将它与javap命令解析得到的内容一一对应起来。
解析结果为:

cafe babe --magic 
0000 0031 --minor_version major_version

----------constants_pool---------------------

0024 --constants_pool_count
0a 0006 0016 --#1=Methodref #6.#22
08 0017 --#2=String #23
09 0018 0019 --#3=Fieldref #24.#25
0a 001a 001b --#4=Methodref #26.#27
07 001c --#5=Class #28
07 001d --#6=Class #29
01 0006 3c69 6e69 743e --#7=Utf-8 <init>
01 0003 2829 56 --#8=Utf-8 ()V
01 0004 436f 6465 --#9=Utf-9 Code
01 000f 4c69 6e65 4e75 6d62 6572 5461 626c 65 --#10=Utf8 LineNumberTable
01 0012 4c6f 6361 6c56 6172 6961 626c 6554 6162 6c65 --#11=Utf8 LocalVariableTable
01 0004 7468 6973 --#12=Utf8 this

01 0038 4c63 6f6d 2f61 6770 616c 6163 652f 6172 7469 636c
652f 6a61 7661 2f62 7974 6563 6f64 652f 6368 6170 7465 7231 2f48 656c 6c6f 576f 726c 643b --#13=Utf8 Lcom/agpalace/article/java/bytecode/chapter1/HelloWorld;

01 0004 6d61 696e  --#14=Utf8 main
01 0016 285b 4c6a 6176 612f 6c61 6e67 2f53 7472 696e 673b 2956 --#15=Utf8 ([Ljava/lang/String;)V
01 0003 6172 67 --#16=Utf8 arg
01 0013 5b4c 6a61 7661 2f6c 616e 672f 5374 7269 6e67 3b --#17=Utf8 [Ljava/lang/String;
01 0009 6865 6c6c 6f77 6f72 64 --#18=Utf8 helloworld
01 0012 4c6a 6176 612f 6c61 6e67 2f53 7472 696e 673b --#19=Utf8 Ljava/lang/String;
01 000a 536f 7572 6365 4669 6c65 --#20=Utf8 SourceFile
01 000f 4865 6c6c 6f57 6f72 6c64 2e6a 6176 61 #21=Utf8 HelloWorld.java
0c 0007 0008 --#22=NameAndType #7:#8
01 000c 4865 6c6c 6f2c 2077 6f72 6c64 --#23=Utf8 Hello,world
07 001e --#24=Class #30
0c 001f 0020 --#25=NameAndType #31:#32
07 0021 --#26=Class #33
0c 0022 0023 --#27=NameAndType #34:#35

01 0036 636f 6d2f 6167 7061 6c61 6365 2f61 7274 6963 6c65 2f6a 6176 612f 6279
7465 636f 6465 2f63 6861 7074 6572 312f 4865 6c6c 6f57 6f72 6c64 --#28=Utf8 com/agpalace/article/java/bytecode/chapter1/HelloWorld

01 0010 6a61 7661 2f6c 616e 672f 4f62 6a65 6374 --#29=Utf8 java/lang/Object
01 0010 6a61 7661 2f6c 616e 672f 5379 7374 656d --#30=Utf8 java/lang/System
01 0003 6f75 74 --#31=Utf8 out
01 0015 4c6a 6176 612f 696f 2f50 7269 6e74 5374 7265 616d 3b --#32=Utf8 Ljava/io/PrintStream;
01 0013 6a6176 612f 696f 2f50 7269 6e74 5374 7265 616d --#33=Utf8 java/io/PrintStream
01 0007 7072 696e 746c 6e #34=Utf8 println

01 0015 284c 6a61 7661 2f6c 616e 672f 5374 7269 6e67 3b29 56 --#35=Utf8 (Ljava/lang/String;)V

-------------constants_pool end--------------------

0021 --access_flag ACC_PUBLIC ACC_SUPER
0005 --this_class #5
0006 --super_class #6
0000 --interfaces_count=0
0000 --fields_count=0

----method_info----------------------------------------------------
0002 --methods_count=2

0001 0007 0008 0001 --public <init> ()V attribute_count=1
0009 0000 002f --Code attribute_length=0x2f
0001 0001 0000 0005 --max_stack=1 max_locals=1 code_length=0x5
2ab7 0001 b1 --code
0000 --exception_table_length=0
0002 --attribute_count=0x2
000a --LineNumberTable 
0000 0006 --attribute_length=6 (excluding the initial six bytes)
0001 --line_number_table_length=1
0000 0006 --start_pc=0 lineNumber=6
000b --LocalVariableTable
0000 000c --attribute_length=12
0001 --local_variable_table_length=1
0000 0005 000c 000d 0000 --start_pc=0 length=0x5 this Lcom/agpalace/article/java/bytecode/chapter1/HelloWorld index=0


0009 --public static 
000e 000f --main ([Ljava/lang/String;)V
0001 --attribute_count=1
0009 0000 0047 --Code attribute_length=0x47
0002 0002 0000 000b  --max_stack=2 max_locals=2 code_length=0xb
1202 4cb2 0003 2bb6 0004 b1 --code
0000 --exception_table_length=0
0002 --attribute_count=0x2
000a --LineNumberTable 
0000 000e --attribute_length=0xe (excluding the initial six bytes)
0003 --line_number_table_length=0x3
0000 0009 --start_pc=0 lineNumber=9
0003 000a --start_pc=3 lineNumber=10
000a 000b --start_pc=10 lineNumber=11
000b --LocalVariableTable
0000 0016 --attribute_length=0x16
0002 --local_variable_table_length=0x2
0000 000b 0010 0011 0000 --start_pc=0 length=0xb arg [Ljava/lang/String; index=0
0003 0008 0012 0013 0001 --start_pc=3 length=0x8 helloWorld Ljava/lang/String; index=1

----------method_info end ------------------------------------------

0001 --attributes_count=1
0014 --Sourcefile 
0000 0002 --attribute_length=0x2
0015 -- HelloWorld.java

Java的class文件结构可以参考《Java Virtual Machine Specification SE8》,或者参考实例分析Java Class的文件结构

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,602评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,442评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,878评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,306评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,330评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,071评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,382评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,006评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,512评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,965评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,094评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,732评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,283评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,286评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,512评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,536评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,828评论 2 345

推荐阅读更多精彩内容