一、平臺無關(guān)性
Java是與平臺無關(guān)的語言赶促,這得益于Java源代碼編譯后生成的存儲字節(jié)碼的文件好芭,即Class文件,以及Java虛擬機(jī)的實(shí)現(xiàn)邻耕。虛擬機(jī)并不關(guān)心Class的來源是什么語言鸥咖,只要它符合一定的結(jié)構(gòu),就可以在Java中運(yùn)行兄世,這樣就出現(xiàn)了JRuby等語言也能夠在JVM中運(yùn)行啼辣。
20140318212143937.png
二、類文件結(jié)構(gòu)
Class文件是一組以8位字節(jié)為基礎(chǔ)單位的二進(jìn)制流御滩,根據(jù)Java虛擬機(jī)規(guī)范的規(guī)定鸥拧,Class文件格式采用一種類似于C語言結(jié)構(gòu)體的偽結(jié)構(gòu)來存儲,這種偽結(jié)構(gòu)中只有兩種數(shù)據(jù)類型:無符號數(shù)和表削解。無符號數(shù)屬于基本數(shù)據(jù)類型富弦,以u1、u2氛驮、u4腕柜、u8來分別代表1、2矫废、4盏缤、8個字節(jié)的無符號數(shù)。表是由多個無符號數(shù)或其他表作為數(shù)據(jù)項(xiàng)構(gòu)成的符合數(shù)據(jù)類型蓖扑,所有的表都習(xí)慣性地以“_info”結(jié)尾唉铜。
三、剖析class文件
首先律杠,來編寫一個簡單的HelloWorld.java程序
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World");
}
}
看看.class文件的內(nèi)容吧
cafe babe 0000 0034 001d 0a00 0600 0f09
0010 0011 0800 120a 0013 0014 0700 1507
0016 0100 063c 696e 6974 3e01 0003 2829
5601 0004 436f 6465 0100 0f4c 696e 654e
756d 6265 7254 6162 6c65 0100 046d 6169
6e01 0016 285b 4c6a 6176 612f 6c61 6e67
2f53 7472 696e 673b 2956 0100 0a53 6f75
7263 6546 696c 6501 000f 4865 6c6c 6f57
6f72 6c64 2e6a 6176 610c 0007 0008 0700
170c 0018 0019 0100 0b48 656c 6c6f 2057
6f72 6c64 0700 1a0c 001b 001c 0100 0a48
656c 6c6f 576f 726c 6401 0010 6a61 7661
2f6c 616e 672f 4f62 6a65 6374 0100 106a
6176 612f 6c61 6e67 2f53 7973 7465 6d01
0003 6f75 7401 0015 4c6a 6176 612f 696f
2f50 7269 6e74 5374 7265 616d 3b01 0013
6a61 7661 2f69 6f2f 5072 696e 7453 7472
6561 6d01 0007 7072 696e 746c 6e01 0015
284c 6a61 7661 2f6c 616e 672f 5374 7269
6e67 3b29 5600 2100 0500 0600 0000 0000
0200 0100 0700 0800 0100 0900 0000 1d00
0100 0100 0000 052a b700 01b1 0000 0001
000a 0000 0006 0001 0000 0001 0009 000b
000c 0001 0009 0000 0025 0002 0001 0000
0009 b200 0212 03b6 0004 b100 0000 0100
0a00 0000 0a00 0200 0000 0300 0800 0400
0100 0d00 0000 0200 0e
JVM定義的class文件結(jié)構(gòu)如下:ClassFile結(jié)構(gòu)
類型 | 名稱 | 數(shù)量 |
---|---|---|
u4 | magic | 1 |
u2 | minor_version | 1 |
u2 | major_version | 1 |
u2 | constant_pool_count | 1 |
cp_info | constant_pool | constant_pool_count-1 |
u2 | access_flags | 1 |
u2 | this_class | 1 |
u2 | super_class | 1 |
u2 | interfaces_count | 1 |
u2 | interfaces | interfaces_count |
u2 | fields_count | 1 |
field_info | fields | fields_count |
u2 | methods_count | 1 |
method_info | methods | methods_count |
u2 attributes_count | 1 | |
attribute_info | attributes | attributes_count |
JDK提供的解析工具
javap -verbose HelloWorld.class
Classfile /Users/yudesong/Project/java/HelloWorld.class
Last modified 2018-1-23; size 425 bytes
MD5 checksum 63e47f1d243e0eb6bc952df3f6ac0d5a
Compiled from "HelloWorld.java"
public class HelloWorld
minor version: 0
major version: 52
flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
#1 = Methodref #6.#15 // java/lang/Object."<init>":()V
#2 = Fieldref #16.#17 // java/lang/System.out:Ljava/io/PrintStream;
#3 = String #18 // Hello World
#4 = Methodref #19.#20 // java/io/PrintStream.println:(Ljava/lang/String;)V
#5 = Class #21 // HelloWorld
#6 = Class #22 // java/lang/Object
#7 = Utf8 <init>
#8 = Utf8 ()V
#9 = Utf8 Code
#10 = Utf8 LineNumberTable
#11 = Utf8 main
#12 = Utf8 ([Ljava/lang/String;)V
#13 = Utf8 SourceFile
#14 = Utf8 HelloWorld.java
#15 = NameAndType #7:#8 // "<init>":()V
#16 = Class #23 // java/lang/System
#17 = NameAndType #24:#25 // out:Ljava/io/PrintStream;
#18 = Utf8 Hello World
#19 = Class #26 // java/io/PrintStream
#20 = NameAndType #27:#28 // println:(Ljava/lang/String;)V
#21 = Utf8 HelloWorld
#22 = Utf8 java/lang/Object
#23 = Utf8 java/lang/System
#24 = Utf8 out
#25 = Utf8 Ljava/io/PrintStream;
#26 = Utf8 java/io/PrintStream
#27 = Utf8 println
#28 = Utf8 (Ljava/lang/String;)V
{
public 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 1: 0
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=1, args_size=1
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String Hello World
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
LineNumberTable:
line 3: 0
line 4: 8
}
SourceFile: "HelloWorld.java"
建議直接安裝IDEA 插件jclasslib