JVM內存結構和Java內存模型


一、JVM

首先看一張JVM結構圖(某度找的)

 

 

主要看運行時數據區,里邊有方法區,堆,java虛擬機棧,本地方法棧,程序計數器。其中方法區和堆是線程共享的,也是JVM進行垃圾收集的區域,java虛擬機棧、本地方法棧和程序計數器是線程私有的。

程序計數器:一塊較小的內存空間,是當前線程所執行的字節碼的行號指示器。此區域是唯一一個不會產生OOM的內存區域。

Java虛擬機棧:每個方法在執行的時候都會創建一個棧幀,用於存放局部變量表、操作數棧、動態鏈接、方法出口等信息。可能會發生StackOverflowError或者OOM。

(1)當一直調用的時候(也就是棧的深度超過了虛擬機所允許的深度),就是跑出此異常。

(2)我的JVM設置如下,-Xss就是單個線程棧的大小,設置為2m。

(為了模擬棧內存溢出,電腦卡死,MMP),不過棧內存溢出很難出現,基本上都是出現StackOverflowError,要想出現棧內存溢出,只能一直創建線程模擬(好像這個也不是一個棧的內存溢出)。

本地虛擬機棧:類似於Java虛擬機棧,不同的是java虛擬機棧執行的java方法,而本地虛擬機棧執行的Native方法(底層用C++所寫)。

方法區:存放已被主要用於存放類的信息,常量、靜態變量、即時編譯器編譯后的代碼等,另外運行時常量池也在這里。可能會出現OOM。(java8之后JVM就將方法區改成元空間,並與堆進行了合並)

(1)設置元空間大小,模擬元空間內存溢出

 

堆:存放對象實例以及數組。可能出現OOM,堆的最小內存值默認是當前操作系統內存的1/64,最大值是1/4。

(1)設置堆大小,模擬堆內存溢出

 

上述理論是從《深入理解java虛擬機》。

 

接下來看一下常用JVM參數:

  1. -Xms10m:相當於-XX:InitialHeapSize=10m,最小堆內存
  2. -Xmx10m:相當於-XX:MaxHeapSize=10m,最大堆內存
  3. -XX:MetaspaceSize:最小元空間大小,用法是-XX:MetaspaceSize=10m
  4. -XX:MaxMetaspaceSize:最大元空間大小
  5. -Xss1024k: 單個線程棧的大小。
  6. -Xmn1G:配置年輕代大小
  7. -XX:+PrintGCDetails:開啟GC收集日志
  8. -XX:+PrintCommandLineFlags:輸出自動優化參數
  9. -XX:UseSerialGC:使用串行垃圾收集器

如何在程序運行的時候查看JVM參數?

(1)先用jps -l獲取進程id

 

(2)然后用jinfo -flag '參數名稱' '進程id'

查看JVM出廠參數命令:

查看JVM根據當前運行系統默認優化后的命令:

 

二、java內存模型(JMM)

(1)JMM本身是一種抽象的概念,描述的是一組規范,定義了變量的訪問方式。

(2)關於同步的規定:

  1. 線程解鎖前,必須將同步變量刷新到主內存中
  2. 線程獲取鎖之后,必須將同步變量刷新到工作內存中
  3. 加鎖和解鎖是同一把鎖。

(3)由於JVM運行程序的主體是線程,而每個線程創建的時候都會有一個工作內存(棧),工作內存是線程的私有數據區域,而java內存模型中規定所有變量都存儲在主內存(線程共享區域),但線程對變量的操作必須是在工作內存中完成,首先要把變量從主內存中拷貝到工作內存中,再對變量進行操作,操作完成再將變量寫回到主內存中。不能直接操作主內存中的變量。

(4)可見性,原子性(不可分割,例如某個線程正在做某個業務的時候,中間不可以被加塞。需要整體完整,要么同時成功,要么同時失敗。),有序性。

 

 

 

=======================================================

我是Liusy,一個喜歡健身的程序猿。

歡迎關注公眾號【Liusy01】,一起交流Java技術及健身。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM