java運行時內存

總說java是一次編譯,處處運行的語言,也即java的平臺無關性。那麼,究竟是誰幫咱們幹髒活累活,由於咱們知道不論是什麼語言,最終都要翻譯成底層的機器碼才能真正在計算機上運行,那麼不一樣的操做系統,不一樣的cpu架構,必然致使機器碼的不一樣,是誰這麼好心?JRM,Java Runtime Environment,針對不一樣的操做系統和硬件架構,會有不一樣的JRM來適配。當咱們將本身的java程序在某個平臺上運行的時候,會派生出一個JVM,Java Virtual Machine,他實際是JRM的一部分,經過在其中仿真模擬各類計算機功能來實現的用戶的意圖。因此,真正在使用的時候,瞭解JVM是java程序員必不可少的技能。html

jvm的功能java

JVM的輸入即爲上圖的class文件,輸出即爲對操做系統的硬件的調用。程序員

JVM實例對應了一個獨立運行的java程序,它是進程級別 。
a) 啓動。啓動一個Java程序時,一個JVM實例就產生了,任何一個擁有public static void main(String[] args)函數的class均可以做爲JVM實例運行的起點 。數組

b) 運行。main()做爲該程序初始線程的起點,任何其餘線程均由該線程啓動。JVM內部有兩種線程:守護線程和非守護線程,main()屬於非守護線程,守護線程一般由JVM本身使用,java程序也能夠代表本身建立的線程是守護線程 。
c) 消亡。當程序中的全部非守護線程都終止時,JVM才退出;若安全管理器容許,程序也可使用Runtime類或者System.exit()來退出 。安全

在類的具體加載執行的過程當中:多線程

首先面臨的是加載器對class文件的一系列工做,當發現類文件合法安全有效以後,就能夠在運行時環境進行分配,而後具體的執行過程有執行引擎來真正運行。架構

在java程序員平常討論中說起的堆和棧,其實都在runtime data area中。jvm

 

如上圖,堆和方法區是jvm中全部線程能夠共享的,可是java棧,本地方法棧,程序計數器,是線程獨享的。函數

a) 程序計數器(PC寄存器)操作系統

因爲在JVM中,多線程是經過線程輪流切換來得到CPU執行時間的,所以,在任一具體時刻,一個CPU的內核只會執行一條線程中的指令,所以,爲了可以使得每一個線程都在線程切換後可以恢復在切 換 以前的程序執行位置,每一個線程都須要有本身獨立的程序計數器,而且不能互相被幹擾,不然就會影響到程序的正常執行次序。所以,能夠這麼說,程序計數器是每一個線程所私有的。因爲程序計數器中存儲的數據所佔空間的大小不會隨程序的執行而發生改變,所以,對於程序計數器是不會發生內存溢出現象(OutOfMemory)的。

b) java棧

 Java棧中存放的是一個個的棧幀,每一個棧幀對應一個被調用的方法,在棧幀中包括局部變量表(Local Variables)操做數棧(Operand Stack)、指向當前方法所屬的類的運行時常量池(運行時常量池的概念在方法區部分會談到)的引用(Reference to runtime constant pool)、方法返回地址(Return Address)和一些額外的附加信息。當線程執行一個方法時,就會隨之建立一個對應的棧幀,並將創建的棧幀壓棧。當方法執行完畢以後,便會將棧幀出棧。

c)本地方法棧

本地方法棧與Java棧的做用和原理很是類似。區別只不過是Java棧是爲執行Java方法服務的,而本地方法棧則是爲執行本地方法(Native Method)服務的

d)堆

Java中的堆是用來存儲對象自己的以及數組(數組引用是存放在Java棧中的)。堆是被全部線程共享的,在JVM中只有一個堆。

e)方法區

與堆同樣,是被線程共享的區域。在方法區中,存儲了每一個類的信息(包括類的名稱、方法信息、字段信息)、靜態變量、常量以及編譯器編譯後的代碼等。在Class文件中除了類的字段、方法、接口等描述信息外,還有一項信息是常量池,用來存儲編譯期間生成的字面量和符號引用。在方法區中有一個很是重要的部分就是運行時常量池,它是每個類或接口的常量池的運行時表示形式,在類和接口被加載到JVM後,對應的運行時常量池就被建立出來。固然並不是Class文件常量池中的內容才能進入運行時常量池,在運行期間也可將新的常量放入運行時常量池中,好比String的intern方法。

方法區可能還有不一樣的名字,好比永久代,或者元信息空間,其實指的都是方法區。

 

java雖然解放了程序員對於空間申請釋放的繁瑣勞動,但若是不瞭解OOM的種類,也會致使在做業出問題時不知道如何處理。

能夠看出,除了程序計數器不會拋出oom外,其餘幾個部分都會可能致使OOM。

另外,多說一句,咱們在用synchronize關鍵字時,到底同步的是什麼,其實就是從主內存(包括java堆和方法區)向子內存(即java棧和native棧)中刷新數據。

 

 參考:

https://www.cnblogs.com/xing901022/p/7725961.html

https://www.cnblogs.com/fubaizhaizhuren/p/4976839.html

相關文章
相關標籤/搜索