hjr-JAVA JVM調優

理解

JVM結構

JVM 執行順序 : class文件-》類裝載器 - 》內存區-》執行引擎

類加載器採用parent模型避免父子加載器重複加載,主要包含,java內部庫加載器-》java擴展類庫加載器-》程序員代碼類加載器-》程序員自定義的類加載器

其中內存區主要包含 方法區 虛擬機棧 本地方法棧 堆 程序計數器

內存分爲靜態內存(方法區,棧)和動態內存(堆),靜態內存回收方式是固定的,GC指的是動態內存,即堆中的內存

虛擬機棧和本地方法棧的區別hi 本地方法棧是爲java native方法服務的,虛擬機棧是爲程序員寫的方法服務的

流程

當我們編寫的class文件進入類裝載器後,java棧總是和線程關聯在一起,每當創建一個線程時,JVM就會爲這個線程創建一個對應的java棧。在這個java棧中又會包含多個棧幀,每運行一個方法就創建一個棧幀,用於存儲局部變量表、操作棧、方法返回值等。每一個方法從調用直至執行完成的過程,就對應一個棧幀在java棧中入棧到出棧的過程。所以java棧是現成私有的。

方法調用=》創建棧幀-》壓入虛擬機棧=》方法執行完畢,棧幀出棧並被銷燬,棧幀保存了局部變量表、操作數棧、動態鏈接、方法出口等數據,棧線程隔離

對JVM內存進行設置和分析可以定位異常代碼,防止內存溢出,強引用(內存溢出也不回收,報錯)、軟引用(內存溢出回收)、弱引用(GC時回收)和虛引用(隨時可以回收),不同的類型對應不同的GC機制,代碼執行過程就是一個壓棧入棧的過程,棧保存基本類型和引用類型,堆保存對象,引用變量就是對象的首地址

內存模型

堆中有主內存
每個線程一個維護一個自己的本地內存,維護堆內存中的共享變量的副本,各個線程從自己的本地內存中存取數據
普通代碼不能保證可見性(線程操作本地內存後主存立刻更新,其他本地內存立刻同步)
使用volatile關鍵字,可以禁止代碼指令優化重排序,和強制訪問主存,保證可見性,但是不能保證原子性

GC

檢測算法

  1. 引用計數法

給一個對象添加引用計數器,每當有個地方引用它,計數器就加1;引用失效就減1,沒引用回收

問題:兩個對象互相引用,永遠無法回收,

2.可達性分析算法

從根集結點檢測,沒引用的回收,根集一般包括java棧中引用的對象、方法區常良池中引用的對象

收集算法

  1. 標記-清除
    先標記要回收的,然後把標記的回收,會造成內存碎片

  2. 複製

用2倍的內存,遍歷區域1,把正在引用的複製到內存2,遍歷結束後回收區域1的全部內存,無內存碎片,耗內存

  1. 標記-整理

先標記要回收的,然後邊回收邊整理內存

  1. 分代收集

堆內存分 年輕代(又分爲8:1:1的三個子區域,用標記-清除) 年老代(滿了用fullGC,不滿用複製) 永生代(程序關閉纔回收)

一個對象在年輕代出生,每經過n檢測未被回收,即移動到下一代。不同代採取不同回收方式

n 是人爲設置和由不同代內存大小決定的

調優

減少 fullGC 和 gc頻率,使用JConsole(內存、CPU曲線等)、Java VisualVM、jsatck(通過線程PID查詢,堆棧內存等),DUMP堆文件分析,等工具檢測

  1. 修改各個內存區域的大小和比例
  2. 檢測內存曲線防止死鎖,死循環等異常代碼
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章