開篇
源代碼HelloWorld.java
/**
* Created by jack on 2017/3/16.
*
* @author jack
* @date 2017/03/16
*/
public class HelloWorld {
public static void main(String[] args){
System.out.println("Hello,World");
}
}
編譯成HelloWorld.class
cafe babe 0000 0031 0022 0a00 0600 1409
0015 0016 0800 170a 0018 0019 0700 1a07
001b 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 0c4c 4865 6c6c 6f57
6f72 6c64 3b01 0004 6d61 696e 0100 1628
5b4c 6a61 7661 2f6c 616e 672f 5374 7269
6e67 3b29 5601 0004 6172 6773 0100 135b
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 0700 1c0c 001d 001e 0100
0b48 656c 6c6f 2c57 6f72 6c64 0700 1f0c
0020 0021 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 2f00 0100 0100 0000 052a
b700 01b1 0000 0002 000a 0000 0006 0001
0000 0007 000b 0000 000c 0001 0000 0005
000c 000d 0000 0009 000e 000f 0001 0009
0000 0037 0002 0001 0000 0009 b200 0212
03b6 0004 b100 0000 0200 0a00 0000 0a00
0200 0000 0900 0800 0a00 0b00 0000 0c00
0100 0000 0900 1000 1100 0000 0100 1200
0000 0200 13
這就是jvm的byte code字節(jié)碼狭园。這一串“天書”,如果不看JVM虛擬機(jī)規(guī)范的人糊治,正常的智商,是看不懂的罚舱。
想看懂這一串十六進(jìn)制的字符井辜,就要了解class文件協(xié)議。
第一行釋義:
magic:魔數(shù)管闷,0xCAFEBABE(cafe babe)
minor_version:占2字節(jié)粥脚,次版本號,0x0000
majro_version:占2字節(jié)包个,主版本號刷允,0x0031,轉(zhuǎn)化為十進(jìn)制為49碧囊,是使用JDK1.5編譯的(JDK1.5:0x0031,JDK1.6:0x0032,JDK1.7:0x0033)
高版本的JDK可以向下兼容以前版本的Class文件树灶,但是無法運(yùn)行以后版本的Class文件,即使文件格式并未發(fā)生變化
如果使用JDK1.5運(yùn)行使用JDK1.6編譯的Class文件糯而,會報:
java.lang.UnsupportedClassVersionError: Bad version number in .class file
就是由于JDK1.6編譯的文件版本號超過了JDK1.5虛擬機(jī)所接受的范圍
Java class文件是二進(jìn)制文件天通。為了便于理解它,JVM提供者提供了javap熄驼,反匯編器(編譯,反編譯的本質(zhì),是“映射”)妒潭。
一切皆是映射(光劍)
使用javap產(chǎn)生的結(jié)果是Java匯編語言着帽。在上面的例子中,下面的Java匯編代碼是通過:
javap -c HelloWorld.class
進(jìn)行反匯編得到的祭芦。
$ javap -c HelloWorld.class
Compiled from "HelloWorld.java"
public class HelloWorld {
public HelloWorld();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
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
}
所以說筷笨,如果你足夠牛逼,不需要使用java語言寫源碼,直接使用jvm指令集寫jvm的匯編語言奥秆。這樣逊彭,什么Scala,Java,Kotlin,Clojure這些運(yùn)行在jvm上的高級編程語言,對你來說构订,真的就是浮云了侮叮。你也不需要糾結(jié)什么OOP,F(xiàn)P悼瘾,Design Pattern, etc.
Class類文件結(jié)構(gòu)
簡單講囊榜,jvm的class文件是針對jvm的私家定制。只要運(yùn)行在jvm上byte code亥宿,都需要按照class文件format來卸勺。否則jvm解析不了。自然無法執(zhí)行烫扼。
官網(wǎng)文檔: The Java Virtual Machine class file format
class文件時java虛擬機(jī)執(zhí)行引擎的數(shù)據(jù)入口曙求,也是java技術(shù)體系的基礎(chǔ)支柱之一,了解class文件的結(jié)構(gòu)對后面進(jìn)一步了解虛擬機(jī)執(zhí)行引擎有很重要的意義映企。
class文件是一組以八位字節(jié)為基礎(chǔ)單位的二進(jìn)制流悟狱,各個數(shù)據(jù)項目嚴(yán)格按照順序緊湊地排列在class文件中,中間沒有添加任何分隔符堰氓,這使得整個class文件中存儲的內(nèi)容幾乎全部都是程序運(yùn)行的必要數(shù)據(jù)挤渐,沒有空隙存在。當(dāng)需要占用8位字節(jié)以上的空間數(shù)據(jù)時双絮,則會按照高位在前的方式分割成若干個8位字節(jié)進(jìn)行存儲浴麻。
ClassFile數(shù)據(jù)結(jié)構(gòu)
ClassFile {
u4 magic;//魔數(shù)(0xCAFEBABE)
u2 minor_version;//次版本號
u2 major_version;//主版本號
u2 constant_pool_count;//常量池容量計數(shù)值
cp_info constant_pool[constant_pool_count-1];//常量池
u2 access_flags;//訪問標(biāo)志
u2 this_class;//類索引
u2 super_class;//父類索引
u2 interfaces_count;//接口計數(shù)器
u2 interfaces[interfaces_count];//接口索引集合
u2 fields_count;//字段計數(shù)器
field_info fields[fields_count];//字段表
u2 methods_count;//方法計數(shù)器
method_info methods[methods_count];//方法表
u2 attributes_count;//屬性表計數(shù)器
attribute_info attributes[attributes_count];//屬性表集合
}
Class文件中,類的全限定名囤攀、字段软免、方法都是使用CONSTANT_Utf8_info類型常量來描述名稱,而該常量的長度由2個字節(jié)表示抚岗,所以類的全限定名或杠、字段名、方法名的最大長度不能超過2個字節(jié)所能表示的最大整數(shù)宣蔚,也就是65535.
博文參考: