我是小蕉。
今天,小蕉我就跟大家聊聊JAVA虛擬機(jī),是個(gè)什么玩意。
通俗來講,JAVA虛擬機(jī)的作用呢,就跟一個(gè)轉(zhuǎn)換插頭,一樣一樣的。同志們?。。∮袥]有遇到這種情況,在找充電插頭,找了半天發(fā)現(xiàn)特么的我是兩頭插頭,而插座,卻只有三頭的T_T??梢钥蘼铮孔詮淖约撼鲩T常備轉(zhuǎn)換頭,哎呀突然天亮了,天亮了?。?!外面插孔是什么樣子的?老子才不在乎。反正老子的手機(jī)充電器都能通過轉(zhuǎn)換插頭,充電啦?。〉锹闊┑牡胤侥?,其實(shí)還是有的,就是我兜里經(jīng)常會放著七八個(gè)轉(zhuǎn)換插頭。。。
Java虛擬機(jī)就是這樣的一個(gè)存在,在各個(gè)平臺上都能跑JAVA程序,但是程序并不在主機(jī)上跑,而是在虛擬機(jī)上跑。所以每個(gè)平臺都各自會有自己的虛擬機(jī)實(shí)現(xiàn)。這樣,JAVA程序就能實(shí)現(xiàn)一次編寫,處處運(yùn)行了。
JAVA跑的時(shí)候呢,跟炒菜似得。首先要把.java剁碎成.class,然后由我這個(gè)類加載器來校驗(yàn)搬運(yùn),在運(yùn)行時(shí)環(huán)境這個(gè)鍋中,用虛擬機(jī)引擎來進(jìn)行炒菜,然后使用自動回收的垃圾桶來進(jìn)行GC,一樣一樣的。
來來來,我們來一個(gè)一個(gè)捋一捋。
怎么把.java剁碎成.class呢?這個(gè).java啊,就是我們普通程序猿寫的那些鬼代碼,而.class呢,就是虛擬機(jī)統(tǒng)一接受的字節(jié)碼。那這個(gè)過程究竟是怎么樣的呢?就要說到編譯器這個(gè)東西了。jdk里有編譯器,叫javac,是用來編譯的。
用一句人都聽不懂的話來說,編譯器就是一個(gè)檢查java語法然后把它按照既定邏輯轉(zhuǎn)換成只有java虛擬機(jī)能看懂的叫字節(jié)碼的玩意。
舉個(gè)栗子:
int i = 5 ;
編譯成
0:bipush ? ?5
2:istore_0
然之后呢,.java就被剁碎成.class文件了。接下來就要上!鍋!啦!
好了,咱再準(zhǔn)備準(zhǔn)備,你說是.class文件就是.class文件啊??我才不信呢。讓我用類加載器的七道工序來準(zhǔn)備準(zhǔn)備。
加載->校驗(yàn)->準(zhǔn)備->處理->初始化->使用->卸載。
共七道工序,由七七四十九重天濃縮而成。
最頂上的是帝君,是BootstrapClassLoader,是所有加載器的神,使用C/C++寫的,其中非常有名的Object就是在這里初始化的呢。它的繼任者天君ExtensionClassLoader,太子ApplicationClassLoader,以及其他的眾神UserDefinedClassLoder。遵循雙親委派模式,就是什么意思呢,就是能讓你老子出面的,你就別自己瞎折騰了,也就是靠關(guān)系了。沒錯(cuò)就是每個(gè)類加載過程中,都會向上層申請加載,上層處理不了的,才會自己去加載。

好了,菜已經(jīng)被證明了它是菜了。終于可以上鍋了,鍋呢,就是執(zhí)行引擎。目前來說分兩類,一類的JIT就是編譯并執(zhí)行的玩意叫JIT編譯器,另一類呢就是直接解析執(zhí)行字節(jié)碼的玩意叫字節(jié)碼解釋器。兩類都存在,虛擬機(jī)上的一般是字節(jié)碼解釋器。這個(gè)鍋有什么用呢?除了用來炒菜之外沒什么卵用。
但是誰說一道菜是能一次性就抄完的呢?肯定要拼盤啊,翻炒,去水,過冷水,就需要一些盤子了吧,JAVA虛擬機(jī)里邊叫運(yùn)行時(shí)環(huán)境,就是用來放一些中間數(shù)據(jù)和中間過程指令的。 從用途分呢,分為六類。分別是歸屬于整個(gè)虛擬機(jī)的堆,方法區(qū),運(yùn)行時(shí)常量池,以及歸屬于每個(gè)線程自有的PC程序計(jì)數(shù)器,JVM方法棧,本地方法棧。每個(gè)盤子都有它自己的用處。我們用一個(gè)例子來說吧。
public class shiter{
public static String b = "some shit";
public void init(){
String a = new String("some shit else");
a+="a";
a.intern();
}
}
好了,讓我們把它們慢慢歸位,放到屬于他們的盤子里邊去。
"some shit" ? ? => 運(yùn)行時(shí)常量池
new String() ? ?=> 堆
"some shit else"=> 運(yùn)行時(shí)常量池
a+="1" ? ? ? ? ?=> JVM方法棧
a.intern ? ? ? ?=> 本地方法棧
組織過程的指令 => PC程序計(jì)數(shù)器
從GC來分呢,可以分為。young{Eden,Survivor-from,Survivor-to},Old,Permanent。一般來說young中的Eden和Survivor比例為3:2,是最容易被GC Collector回收掉的。Old區(qū)域則比較難回收。Permanent要么不回收,只有在Perm滿的時(shí)候或者FullGC的時(shí)候會回收。各種GC回收策略后面可以單獨(dú)開一門課了,總之呢,GC就跳軟柿子捏,誰背后沒有程序引用靠山了,就會被清掉,如果沒空間了,那么就全部一起捏扁。
好了菜就炒到這里,需要找我當(dāng)大廚的,就長按二維碼關(guān)注吧,喜歡的就分享一下唄。