當前位置:
首頁 > 知識 > 初始jvm(一)——jvm內存區域與溢出

初始jvm(一)——jvm內存區域與溢出


jvm內存區域與溢出

為什麼學習jvm

  • 木板原理,最短的一塊板決定一個水的深度,當一個系統垃圾收集成為瓶頸的時候,那麼就需要你對jvm的了解掌握。
  • 當一個系統出現內存溢出,內存泄露的時候,因為你懂jvm知識,可以更加快速定位錯誤,可以通過參數去合理設置各內存區域的內存容量。
  • 因為你對jvm的認識,寫代碼的時候會潛意識地讓你注意代碼質量,可能你會說是那是小小的性能提升,但是量變會導致質變的。

jvm內存區域

jvm內存劃分

  • 方法區
  • 虛擬機棧
  • 本地方法棧
  • 程序計數器

程序計數器

  • 當前線程所執行的位元組碼的行號指示器。
  • 因為cpu的每個核心只能同時運行一個線程,所以當一個線程執行完時間片後切換到另一個線程,切換時為了能恢復到正確的執行位置,所以需要程序計數器(學過計算機組成原理的應該比較熟悉)。
  • 如果是線程執行的是一個java方法那麼此時計數器記錄的是正在執行的虛擬機位元組碼指令的地址。如果是nativ方法(非java代碼),計數器值為空。

虛擬機棧

  • java執行的內存模型,棧由棧幀組成,線程調用一個java方法時,創建一個棧幀,方法返回時,棧幀彈出。棧幀入棧出棧的過程就是方法開始結束的過程
  • 棧幀存儲局部變數區(存放基本數據類型數據,對象指針),操作數棧(存放操作數,比如加法運算的時候操作數棧取值,計算後再壓入棧),動態鏈接,方法出口。

本地方法棧

  • 和虛擬機棧作用類似,只不過服務對象不同,本地方法服務對象是非java方法,虛擬機棧服務對象是java方法

方法區

  • 存放類的信息、常量、靜態變數等
  • 運行時常量池是方法區一部分,主要存放字面量(如final修飾的變數)和符號引用量(編譯原理方面)

  • 存放對象,對象要在堆上分配內存
  • 堆分為年輕代和年老代
  • 年輕代分為伊甸區(Eden space)和倖存者區(Survivor space)
  • 倖存區分為from和to空間

總結

  • jvm的內存區域劃分為程序計數器,虛擬機棧,本地方法棧,方法區,堆。
  • 程序計數器,虛擬機棧和本地方法棧都是線程獨享的,而方法區和堆是線程共享的

溢出

理清概念

  • 操作系統分配給進程的內存是有限的,而jvm的內存區域我們已經知道,當我們設置好堆和方法區的最大容量後,那麼剩下的內存將分配給虛擬機棧和本地方法區和程序計數器(佔用內存少)。
  • 兩種常見的溢出異常,一種OutOfMemoryError(OOM),一種StackOverflowError。

各區溢出情況

  • 堆溢出,當我們創建的對象佔用的內存超過最大堆容量時候,會拋出OOM
  • 本地方法棧和虛擬機棧溢出:當請求的棧深度超過虛擬機所允許的深度的時候會拋出棧溢出,這種情況我們在使用遞歸出錯的時候經常遇到;還有就是出現OOM的情況,我們知道分配給這兩個棧的內存是有限,和線程數和線程的棧內存有關係,那麼當我們其中任意一個過大的話,都有可能造成OOM
  • 方法區和運行時常量池溢出:方法區存放類的信息,有時我們用的框架在動態代理的時候會動態生成CLASS,這個時候有可能會出現方法區的OOM;而常量池溢出我們可以用String的intern方法(如果常量池沒有與字元串相等的字元串,就將這個字元串存入方法區)進行模擬。

設置各區的jvm參數

  • 設置堆的最小值-Xms,堆的最大值-Xmx
  • 設置永久代(jdk8之前用永久代來實現方法區)的最小值-XX:PermSize ,最大值-XX:MaxPermSize
  • 設置棧容量-Xss

延伸

關於創建字元串

String s2=new String("jiajun");
String s6=new String("jiajun");
System.out.println(s2==s6);

  • 結果為false,都存放在堆內存,但是兩個地方。

String s6=new String("jiajun");
String s1="jiajun";
System.out.println(s1==s6);

  • 結果為false,s6存放在堆當中,而s1存放在常量池當中

String s1="jiajun";
String s7="jiajun";
System.out.println(s1==s7);

  • 結果為true,都是存放在常量池

String s4="jia";
String s5=s4+"jun";
String s1="jiajun";

System.out.println(s1==s5);

  • 結果為false,變數的值在運行的時候才確定,所以此時s5實際上是new一個對象

String s3="jia"+"jun";
String s1="jiajun";
System.out.println(s1==s3);

  • 結果為true,此時s1 s3都是指向常量池一個string

String s1="jiajun";
String s8=new String("jia")+"jun";
System.out.println(s1==s8);

  • 結果為false,此時s8同樣是new出來一個對象

我覺得分享是一種精神,分享是我的樂趣所在,不是說我覺得我講得一定是對的,我講得可能很多是不對的,但是我希望我講的東西是我人生的體驗和思考,是給很多人反思,也許給你一秒鐘、半秒鐘,哪怕說一句話有點道理,引發自己內心的感觸,這就是我最大的價值。(這是我喜歡的一句話,也是我寫博客的初衷)

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 達人科技 的精彩文章:

Python判斷文件是否存在的三種方法
《HelloGitHub》第 16 期
vue怎麼樣創建組件呢?
在運行階段修改應用配置文件
python數據結構鏈表之單向鏈表

TAG:達人科技 |

您可能感興趣

Facebook 開源 oomd,一種處理內存溢出的新方法
Facebook 開源內存溢出殺手 oomd
Jenkins內存溢出的處理方法
necp_client_action系統調用中的堆溢出漏洞分析
Netatalk緩衝區溢出漏洞的發現與利用
CTF實戰28 Windows緩衝區溢出
「Red Velvet」「新聞」190214 溢出屏幕的chic魅力 澀琪品牌B-Cut宣傳照公開!
幽靈安全漏洞 Spectre1.1 新變種曝光 源於投機執行與緩衝區溢出;Facebook 首次因數據泄密醜聞遭罰款
Super Junior出席新團綜製作發佈會 快要溢出屏幕的綜藝感!
「Red Velvet」「分享」190728 姜澀琪好酷一女的!溢出屏幕的帥氣是真實存在的
Linux中create_elf_tables函數整型溢出漏洞分析(CVE-2018-14634)
Angr AEG:堆溢出之Exploit自動生成
linux緩衝區溢出漏洞簡介
記一次內存溢出的分析經歷 : thrift 帶給我的痛
ASLR 是如何保護 Linux 系統免受緩衝區溢出攻擊的
Microsoft Windows JET資料庫引擎堆溢出漏洞CVE-2018-1003分析
linux溢出提權小記
Angelababy秀舞技仙氣飄飄,網友:這可愛的小表情都要溢出屏幕了!
div中文字內容溢出常見的解決方法
3unshine站在垃圾堆里拍大片,味道簡直要溢出屏幕