大數據開發之JVM基礎知識點

JVM

認知

      熟悉jvm架構以及垃圾回收機制以及相應的參數調優,有過在linux進行系統優化的經驗

      線程和操作系統有關

      過程

           1)class文件通過類加載器加進內存區域---class loader類加載器

                 負責加載class文件,class文件在文件開頭有特定的文件標示,並且ClassLoader只負責class文件的加載,至於它是否可以運行,則由Execution Engine決定

           2)Execution Engine執行引擎負責解釋命令,提交操作系統執行

           3)Native Interface 本地接口

                 private native void start0();本地庫接口

                      java native interface  JNI

                            調操作系統底層函數庫,調c的函數

                 本地接口的作用是融合不同的編程語言爲java所用,它的初衷是融合C/C++程序,java誕生的時候是C/C++橫行的時候,要想立足,必須調用C程序,於是就在內存中專門開闢了一塊區域處理標記爲native代碼,它的具體做法是Native Method Stack中登記native方法,在Execution Engine執行時加載native libraies.

                      目前該方法的使用越來越少了,除非是與硬件有關的應用,比如通過java程序驅動打印機,或者java系統管理生產設備,在企業級應用中已經比較少見

                            因爲現在的異構領域間的通信很發達,比如可以使用Socket通信,也可以使用web service等等,不多介紹

           4)Runtime data area 運行數據區

                 Method Area方法區

                      方法區被所有線程共享,所有字段和方法字節碼,以及一些特殊方法如構造函數,接口代碼也在此定義。簡單說,所有定義的方法的信息都保存在該區域,此區屬於共享區間。

                            靜態變量+常量+類信息+運行時常量池存在方法區中+實例變量存在堆內存中

                 PC Register 程序計數器

                      每個線程都有一個程序計數器,就是一個指針,指向方法區中的方法字節碼(下一個將要執行的指令代碼),由執行引擎讀取下一條指令,是一個非常小的內存空間,幾乎可以忽略不計

                 Native Method Stack 本地方法棧

                      它的具體做法是Native Method Stack中登記native方法,在Execution Engine執行時加載native libraies

      棧管運行,堆管存儲

           棧也叫棧內存,主管java程序的運行,是在線程創建時創建,它的生命期是跟隨線程的生命期,線程結束棧內存也就釋放,對於棧來說不存在垃圾回收問題,只要線程一結束該棧就over,生命週期與線程一致,是線程私有的。基本類型的變亮和對象的引用變亮都是在函數的棧內存中國分配

                 每執行一個方法都會產生一個棧幀,保存到棧(後進先出)的頂部,頂部棧就是當前的方法,該方法執行完畢後會自動將此棧幀出棧

           棧幀中主要保存3類數據

                 本地變量:輸入參數和輸出參數以及方法內的變亮

                 棧操作:記錄出棧,入棧的操作

                 棧幀數據:包括類文件,方法等等

      判斷JVM優化在哪裏

           方法區Method Area

           堆Heap

      三種JVM

           Sun公司的HotSpot

           BEA公司的JRockit

           IBM公司的J9 VM

堆Heap

      新生區

           伊甸區(Eden Space)

                 new對象

                      JVM垃圾回收器將對伊甸園區進行垃圾回收(Minor GC)

                      大概內存使用70%的時候,銷燬九成以上的對象,剩下的進入倖存0區

           倖存0區(Survivor 0 Space)

           倖存1區(Survivor 1 Space)

      養老區(Tenure Generation Space)

           養老區用於保存從新生區篩選出來的java對象,一般池對象都在這個區域活躍

           如果養老區滿了,那麼這個時候將產生Major GC(FullGC),進行養老區的內存清理

               如果養老區執行了Full GC之後發現依然無法進行對象的保存,就會產生OOM異常“OutOfMemoryError”

      永久存儲區(Permanent Space)

           永久存儲區是一個常駐內存區域,用於存放JDK自身攜帶的Class,Interface的元數據,也就是說它存儲的是運行環境必須的類信息,被裝載進此區域的數據是不會被垃圾回收器回收掉的,關閉JVM纔會釋放此區域所佔用的內存

           如果出現java.lang.OutOfMemoryError:PermGen space,說明是java虛擬機對永久性代Perm內存設置不夠。一般這種情況,都是程序啓動需要加載大量的第三方jar包。

                 例如:在一個tomcat下部署了太多的應用。或者大量動態反射生成的類不斷被加載,最終導致Perm區被佔滿

                      jdk1.6及之前:有永久代,常量池在方法區

                      jdk1.7:有永久代,但已經逐步“去永久代”,常量池在堆

                      jdk1.8及之後:無永久代,常量池在元空間

      如果出現java.lang.OutOfMemoryError:java heap sapce異常,說明java虛擬機的堆內存不夠。原因有二:

           1、java虛擬機設置的堆內存設置不夠,可以通過參數-Xms、-Xmx來調整

           2、代碼中創建了大量大對象,並且長時間不能被垃圾收集器收集(存在被引用)

 

JDK1.8

      JDK1.8之後將最初的永久代取消了,由元空間取代

           目的:將HotSpot與JRockit兩個虛擬機標準

      JVM Heap

           -Xms  -Xmx

      Young Gen

           -Xmn

      堆內存調優簡介

           -Xms

                 設置初始分配大小,默認爲物理內存的“1/64”

           -Xmx

                 最大分配內存,默認爲物理內存的“1/4”

           -XX:+PrintCGDetails

                 輸出詳細的CG處理日誌

GC

      是什麼

           頻繁手機Young區

           較少收集Old區

           基本不動Perm區

      四大算法

           複製算法:MinorGC(普通GC)

                 新生代中使用的是Minor GC,這種GC算法採用的是複製算法(Copying)

                 Minor GC會把Eden中所有活的對象都移到Survivor區域中,如果Survivor區中放不下,那麼剩下的活的對象就被移到Oldgeneration中,也即一旦收集後,Eden就變成空的了

                      當對象在Eden(包括一個Survivor區域,這裏假設是from區域)出生後,在經過一次Minor GC後,如果對象還存活,並且能夠被另外一塊Survivor區域所容納(上面已經假設爲from區域,這裏應爲to區域,即to區域有足夠的內存空間來存儲Eden和From區域中存活的對象),則使用複製算法將這些仍然還存活的對象複製到另外一塊Survivor區域(即to區域)中,然後清理所使用過的Eden以及Survivor區域(即from區域),並且將這些對象的年齡設置爲1,以後對象在Survivor區每熬過一次Minor GC,就將對象的年齡+1,當對象的年齡達到某個值時(默認爲15歲,通過-XX:MaxTenuringThreshold來設定參數),這些對象就會成爲老年代

                      -XX:MaxTenuringThreshold

                            設置對象在新生代中存活的次數

                 複製算法不會產生內存碎片且對象完整不丟

                 複製算法彌補了標記/清除算法中,內存佈局混亂的缺點。

                 缺點

                      1、他浪費了一半的內存,這太要命了

                      2、如果對象存活率高,我們可以極端一點,假設是100%存活,那麼我們需要將所有對象都複製一遍,並將所有引用地址重置一遍。複製這一工作所花的時間,在對象存活率達到一定的程度時,將會變得不可忽視。所以從以上描述不難看出,複製算法要想使用,最起碼對象的存活率要非常低纔行,而且最重要的是,我們必須要克服50%內存的浪費

           標記清除/標記整理算法:FullGC又叫MajorGC(全局GC)

                 老年代一般是由標記清除或者是標記清除與標記整理的混合實現

                 標記清除(Mark-Sweep)

                      1、標記(Mark)

                            從根集合開始掃描,對存活對象進行標記

                      2、清除(Sweep)

                            掃描整個內存空間,回收未被標記的對象,使用free-list記錄可以區域

                      優缺點

                            優點:不需要額外的空間

                            缺點:兩次掃描耗時嚴重,會產生內存碎片

                 標記整理(Mark-Compact)

                      標記---整理--清除:達到內存連續,不需要額外的空間,不產生內存碎片

                      劣勢

                            標記整理算法唯一的缺點就是效率也不高,不僅要標記所有存活對象,還要整理所有存活對象的引用地址。從效率上來說,標記整理算法要低於複製算法

           引用計數法

                 已經被淘汰,解決不了雙端循環引用的問題

      總結

           內存效率

                 複製算法>標記清除>標記整理(此處的效率只是簡單的對比時間複雜度,實際情況不一定如此)

           內存整齊度

                 複製算法=標記整理>標記清除

           內存利用率

                 標記整理=標記清除>複製算法

      分代收集算法

           最合適的算法

                 就是根據JVM不同的代,量體裁衣

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