本猿2013年畢業,到現在已經有五年了,雖然一直從事java工作,但是一直是寫業務代碼,設計業務産品那種,工作節奏比較散漫,最近才深深的感覺到我的能力跟畢業一兩年的沒多少差别,剛好最近工作閑了下來,開始看别人的一些部落格,看了一些感悟,真的很受打擊,不信你們看看,原來不知不覺我已經淪為不思進取,不求上進的人了
http://www.zuoxiaolong.com/html/article_184.html#
https://blog.csdn.net/chenssy/article/details/53738264
最近開始瘋狂買書補救,看書如果不去總結,那麼理論的知識肯定過不了幾天就會忘掉,我打算重新開始寫部落格了,雖然我的文筆比較菜,總結能力也不強,不管了,自己寫的自己能看懂就好了
第一篇就寫一寫java虛拟機記憶體模型,簡稱JMM的結構吧:
JVM記憶體模型主要分為以下幾個區域:
程式計數器,java虛拟機棧,本地方法棧,堆記憶體,方法區,運作時常量池
程式計數器
程式計數器是線程私有的區域,很好了解嘛~,每個線程當然得有個計數器記錄目前執行到那個指令。占用的記憶體空間小,可以把它看成是目前線程所執行的位元組碼的行号訓示器。如果線程在執行Java方法,這個計數器記錄的是正在執行的虛拟機位元組碼指令位址;如果執行的是Native方法,這個計數器的值為空(Undefined)。此記憶體區域是唯一一個在Java虛拟機規範中沒有規定任何OutOfMemoryError情況的區域。(這段是抄别人的,原諒我自己表述會誤導人)
虛拟機棧
虛拟機棧也是線程私有的,就是一個線程會配置設定一個棧,用于存放基本類型,引用類型的棧幀
- 局部變量表的建立是在方法被執行的時候,随着棧幀的建立而建立。而且,局部變量表的大小在編譯時期就确定下來了,在建立的時候隻需配置設定事先規定好的大小即可。此外,在方法運作的過程中局部變量表的大小是不會發生改變的。
-
Java虛拟機棧會出現兩種異常:StackOverFlowError和OutOfMemoryError。
a) StackOverFlowError:
若Java虛拟機棧的記憶體大小不允許動态擴充,那麼當線程請求棧的深度超過目前Java虛拟機棧的最大深度的時候,就抛出StackOverFlowError異常。
b) OutOfMemoryError:
若Java虛拟機棧的記憶體大小允許動态擴充,且當線程請求棧時記憶體用完了,無法再動态擴充了,此時抛出OutOfMemoryError異常。
- Java虛拟機棧也是線程私有的,每個線程都有各自的Java虛拟機棧,而且随着線程的建立而建立,随着線程的死亡而死亡。
注:StackOverFlowError和OutOfMemoryError的異同?
StackOverFlowError表示目前線程申請的棧超過了事先定好的棧的最大深度,但記憶體空間可能還有很多。
而OutOfMemoryError是指當線程申請棧時發現棧已經滿了,而且記憶體也全都用光了。
本地方法棧
本地方法棧與虛拟機棧 是比較類似的,都會抛出StackOverFlowError異常和OutOfMemoryError異常,本地方法棧是為本地方法Native建立的,在hotspot虛拟機中,本地方法棧與虛拟機棧是在同一區域,,,待補充
堆記憶體
這個區域就是jvm的倉庫,基本上大部分的對象都存儲在這個區域,而且這個區域是線程共享的,不像程式計數器或者虛拟機棧是線程唯一的,這個區域也是垃圾回收最活躍的場所,也最容易發生記憶體洩露,OOM的部分,一般虛拟機把這個區分去成 年輕代和老年代,年輕代一般是用完就回收的局部變量,老年代是逃過幾次GC回收,多次被引用的對象存放的區域。堆記憶體不足的時候,就是無法配置設定記憶體去建立對象,就會抛出OutOfMemoryError: java heap space ,這個時候說明堆記憶體不足了,需要檢查代碼是不是有大量對象生成,或者存在記憶體洩露,
通過調節 -Xms,-Xmx來調整堆的大小,前提是要根據實體機的實際記憶體來調整。
方法區
方法區是存儲類的class檔案内容和資料結構,靜态變量,常量,可以參考類加載器的加載過程。jvm加載class檔案時,會把class檔案的位元組流内容和檔案結構,轉換成方法區的資料結構和内容,類加載時會生産一個class對象作為外部調用類方法的入口,這是唯一存儲在方法區的對象吧。方法區有的地方又稱 “永久代”。方法區記憶體不夠用的時候也會報 java.lang.OutOfMemoryError: PermGen space 的錯誤。可以通過調節-XX:PermSize=64 M -XX:MaxPermSize=128 M 參數來調大方法區的記憶體。
運作時常量池
是存在方法區的一小塊區域,一般是存放類編譯的時候的常量或者符号引用,例如有些基本的資料就存儲在這裡
Byte,Short,Integer,Long,Character,Boolean 預設建立了數值在 -128-127區域的對應的緩存
Integer a = 127;
Integer b =127;
system.out.print(a==b) ——> true
Integer a = 150;
Integer b =150;
system.out.print(a==b) ——> false
直接記憶體
這個區域不在虛拟機的掌控範圍,比如實作NIO時會直接使用直接記憶體,具體的查資料好吧。
好吧,第一篇就寫到這裡,感覺自己真的好水,還是科班出身的,如果你跟我類似,工作了四五年,還是混在小公司,享受着朝九晚五,又有些想法的話,不如跟我一起對java有一個深入的學習,不管技術能提高多少,至少我們努力過。
最近在看幾本書,收貨确實挺大的,推薦一下:
java 并發程式設計實戰
深入了解java虛拟機
effectivjava
慢慢看吧,
不喜歡勿噴啊,這些大部分都是我靠腦子回憶的,有些細節還是翻書找的,今年開始java深入學習之路
下一篇繼續講jvm GC的内容