JVM基礎快速入門篇

Java是一門可以跨平臺的語言,但是Java本身是不可以實現跨平臺的,需要JVM實現跨平臺。javac編譯好後的class文件,在Windows、Linux、Mac等系統上,只要該系統安裝對應的Java虛擬機,class文件都可以運行。達到”一次編譯,到處運行”的效果。

一、JVM是什麼?

而JVM到底是什麼呢?引用百度百科對JVM的介紹:

JVM是Java Virtual Machine(Java虛擬機)的縮寫,JVM是一種用於計算設備的規範,它是一個虛構出來的計算機,是通過在實際的計算機上仿真模擬各種計算機功能來實現的。

二、JVM架構知識

1.JVM主要包含類裝載器、運行時數據區(內存模型)、執行引擎。裏面內存模型有可以細分包括本地方法棧、堆、棧(線程)、方法區(元空間)、程序計數器。如圖所示:

 

1.類裝載器的作用就是負責加載class文件,class文件在文件開頭有特定的文件標示,將class文件字節碼內容加載到內存中,並將這些內容轉換成方法區中的運行時數據結構並且ClassLoader只負責class文件的加載,至於它是否可以運行,則由執行引擎(Execution Engine)決定。類加載器又有四大類加載器:

  • 啓動類加載器(Bootstrap ClassLoader):負責加載JRE核心類庫,像JRE中的rt.jar等(C/C++);

  • 擴展類加載器(Extension ClassLoader):負責加載JRE擴展目錄ext中的jar包;

  • 系統類加載器(Application ClassLoader):負責加載ClassPath路徑下的類包;

  • 自定義的類加載器(User ClassLoader):只加載指定目錄下的jar和class,想加載其它位置的類或jar時得自行定義類加載器;

2.JVM中,對象都是在堆中分配內存空間的,棧只用於保存局部變量和臨時變量,如果是對象,只保存引用,實際內存還是在堆中。棧的特點是先進後出,假設一個main方法,裏面執行了一個方法,我們是後執行的那個方法即那個線程,但是執行完畢後,那個線程是先銷燬的。每個方法在執行的同時都會創建一個棧幀,用於存儲局部變量表(存放局部變量的)、操作數棧(存放需要運算的數據)、動態鏈接、方法出口(執行完方法 回到main方法的位置)等信息,每一個方法從調用直至執行完成的過程,就對應着一個棧幀在虛擬機中入棧到出棧的過程。即一個方法對應一塊棧幀內存區域(存放本方法的局部變量)。

3.方法區存儲已被虛擬機加載的類信息、常量(堆中的對象常量地址)、靜態變量、即時編譯器編譯後的代碼等數據。

4.本地方法棧和棧的作用類似,但是它服務的對象是native方法,該方法得由c語言來實現。

5.程序計數器作用是當CPU多線程切換的時候,切回到當前線程的時候,回到程序計數器計數的位置,繼續執行。

三、堆內存的結構模型

新生代包括Eden加上2個survivor區,執行minor gc之後,大多數的對象會被回收,活着的進入s0,再次minor gc,活着的對象eden+s0->s1,再次minor gc,eden+s1->s0…這裏虛擬機採取了分代收集的思想來管理內存,JVM給每個對象一個對象年齡計數器,分代年齡達到15後即對象被執行了15次minor gc後移入老年代。除此之外,s區裝不下的大對象也會直接進入老年代。

最後,老年代存的就是一些大對象和需要連續內存空間的對象(靜態變量、緩存、線程池等),老年代滿了的話,會執行Full GC垃圾收集。官網對Full GC的解釋中介紹了個詞”Stop-The-World”,它會把所有的應用線程停掉,這時候系統會卡掉。JVM虛擬機調優的目標就是減少full gc即減少STW。

四、垃圾回收機制

堆裏面存放new的對象和數組,Java優於其他語言一個很重要的原因就是它能自動處理垃圾對象,也就是有垃圾回收機制(GC)。有了垃圾回收機制有幾點好處編程簡單,系統不容易出錯。

1.什麼是垃圾?

我們把沒有任何引用指向的對象或者一堆對象(循環引用)定義爲垃圾。

2.系統如何定位垃圾

  • 引用計數算法-簡單且高效但是主流的Java虛擬機裏並沒有選用引用計數算法來管理內存,因爲它不能解決循環引用的問題。
  • 根可達分析算法-將”GC Roots”對象作爲起點,從這些節點開始向下搜索引用的對象,找到的對象都標記爲非垃圾對象,其餘未標記的對象都是垃圾對象。線程棧的本地變量、靜態變量、本地方法棧的變量等等都可以稱作GC Roots跟節點。如圖:

3.常見的垃圾回收算法

  • 複製算法-沒有碎片 浪費內存空間(目前使用新生代使用的是複製算法)
  • 標記清除-位置不連續 產生內存碎片
  • 標記壓縮-沒有碎片 效率偏低

複製算法它將可用內存按容量分爲大小相等的兩塊,每次只使用其中的一塊,當這一塊的內存用完了,就將還存活的對象複製到另外一塊上面,然後再把已使用過的內存空間一次清理掉。

五.常見垃圾回收器

新生代收集器:Serial、ParNew、Parallel Scavenge
老年代收集器:CMS、Serial Old、Parallel Old
整堆收集器: G1

jdk1.8 默認垃圾收集器Parallel Scavenge(新生代)+Parallel Old(老年代)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章