JVM从入门到放弃——JVM内存模型
前言
Java和C或者是C++相比較而言,最大的區別是C系列的程序員在編寫代碼的時候,總是要對程序中的變量進行釋放內存的操作,所以在編寫C或者是C++的程序員需要格外的謹慎,因為他們對程序的內存有著很高的權限,這樣雖然是特點但是同時也是缺點,畢竟every coin has two sides。所以跟Java語言相比而言,Java把內存的管理直接交付給JVM,因為JVM的存在,Java程序員能夠更關注業務的實現,而不需要對內存的管理過于關注。但是我們在編程的時候,有時候會出現OutOfMemoryError之類的錯誤,這就是JVM內存溢出的錯誤。這樣如果我們對Java虛擬機對內存的管理,我們就不能很好的解決類似的問題,所以我們還是要對Java的內存管理要有一定的理解,對我們后期對Java代碼調優也是有一定的幫助。
Java虛擬機內存模型
?
根據上圖可以看出來JVM的運行時數據區域主要就是方法區,虛擬機棧,虛擬機堆內存,本地方法區和程序計數器。下面就來看看這些個內存區域都是用來存儲哪些數據的。
Java虛擬機棧
方法區是線程私有的內存區域,聲明周期與線程相同。虛擬機棧描述的是Java方法執行的內存模型,每個方法執行的時候,虛擬機會以棧幀的形式壓入到棧中,這里的棧也是一種先進后出的數據結構。棧幀通常是用來存儲局部變量表,操作數棧,幀數據區等信息。每個方法的調用和結束都是入棧和出棧的操作。由于每次方法的調用都會生成對應的棧幀,棧幀會占用一定的??臻g,因此,如果棧幀的空間不足,函數的調用就無法進行下去,當請求的棧的深度大于最大的可用棧深度的時候,系統就會拋出StackOverflowError的溢出錯誤。?
局部變量表存放編譯期可以知道的各種基本數據類型(boolean,byte,char,short,int,float,long,double),對象引用和returnAddress類型。其中64位長度的long和double類型的數據會占用2個slot局部變量空間,其余的都是一個slot。局部變量表所需要的內存空間在編譯期間完成分配,運行期間不會改變局部變量表的大小。?
代碼實現StackOverflowError的溢出錯誤
在運行的時候,修改JVM參數,通過修改-Xss128K可以改變虛擬機棧的大小,我第一次是128K第二次是256K,看執行的結果
遞歸java棧的深度是 : 994 Exception in thread "main" java.lang.StackOverflowError at java.lang.Integer.<init>(Unknown Source) at java.lang.Integer.valueOf(Unknown Source) at com.jvm.method_region.MethodRegionTest.method1(MethodRegionTest.java:8) at com.jvm.method_region.MethodRegionTest.method1(MethodRegionTest.java:9) at com.jvm.method_region.MethodRegionTest.method1(MethodRegionTest.java:9) at com.jvm.method_region.MethodRegionTest.method1(MethodRegionTest.java:9) at com.jvm.method_region.MethodRegionTest.method1(MethodRegionTest.java:9)- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
第二次
遞歸java棧的深度是 : 2475 Exception in thread "main" java.lang.StackOverflowError at java.lang.Integer.<init>(Unknown Source) at java.lang.Integer.valueOf(Unknown Source) at com.jvm.method_region.MethodRegionTest.method1(MethodRegionTest.java:8) at com.jvm.method_region.MethodRegionTest.method1(MethodRegionTest.java:9) at com.jvm.method_region.MethodRegionTest.method1(MethodRegionTest.java:9) at com.jvm.method_region.MethodRegionTest.method1(MethodRegionTest.java:9) at com.jvm.method_region.MethodRegionTest.method1(MethodRegionTest.java:9) at com.jvm.method_region.MethodRegionTest.method1(MethodRegionTest.java:9)- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
在eclipse改變JVM的參數操作?
?
<————————-這是分隔符————————————->?
本地方法棧
本地方法棧和虛擬機棧類似,但是他們也是有區別的,區別就是虛擬機棧是調用java方法的時候,會把棧幀壓入棧中,而本地方法棧是調用的native方法,native是由C++編寫的。同時本地方法棧也會和虛擬機棧一樣也是會爆出來StackOverflowError和OutOfMemoryError的錯誤。OutOfMemoryError的錯誤是在虛擬機的棧內存可以自動擴展的情況下,不停的將棧幀數據壓入到棧中,以至于虛擬機不停的申請內存,最后導致內存的溢出,所以爆出來OutOfMemoryError錯誤。
虛擬機堆
Java Heap是Java虛擬機所管理的內存最大的一塊,這一塊的內存區域是所有線程共享的。此內存區域是用來存放對象實例,幾乎所有的對象實例以及數組都在這里分配內存。Java Heap還可以細分為新生代區和老年代區,而新生代區還可以分為eden區,from區和to區,from和to的大小是一樣的。在絕大數的情況下,對象是先分配在eden區,在第一次垃圾回收后,如果對象還存活著,那么該對象就會進入到from區或者是to區,然后每經過一次垃圾回收,對象依然存活著,它的年紀就會增加1。當對象的年紀到達一定的條件后,該對象就會進入到老年tenured區。
程序計數器
Program Counter是每個線程的私有空間,Java虛擬機會為每一個線程創建PC寄存器,在任意時刻,一個線程總是在執行一個方法,正在執行的方法稱為當前方法。如果當前方法不是本地方法,PC寄存器就會指向當前正在被執行的指令。如果當前方法是本地方法,那么PC寄存器的值就是undefined。
方法區
方法區也是線程共享的內存區域,用于保存系統的類信息,比如類的字段,方法,常量池等,方法區的大小決定了系統可以保存多少個類如果系統定義了太多的類,同樣會導致方法區的溢出。在JDK1.6和JDK1.7中,方法區可以理解為永久區(Perm)。永久區可以使用參數-XX:PermSize和-XX:MaxPermSize指定,默認情況下,-XX:MaxPermSize為64MB。一個大的永久區可以保存更多的信息。如果系統中使用一些動態代理,那么就有可能在運行時生成大量的類。在JDK1.8中,永久區已經被徹底移除,用元數據區來代替。元數據區可以使用-XX:MaxMetaspaceSize指定,元數據區使用的系統的直接內存。如果不指定元數據的大小,程序會耗盡所有的內存。
package com.jvm.perm;import net.sf.cglib.beans.BeanGenerator;public class PermTest { class Perm{ String name; public String getName(www.bomaoyule.cn) { return name; } public void setName(String name) { this.name = name; } } public static void main(String[www.yingka178.com?] args) { try { for (int i = 0; i < 1000000; i++) { BeanGenerator generator = new BeanGenerator(www.078881.cn?); generator.setSuperclass(Perm.class); generator.addProperty("name", String.class); generator.create(www.chaoyueyule.com/); } } catch (Exception www.dongfan178.com e) www.mcyllpt.com/?{ // TODO: handle exception加了虛擬機參數-XX:+PrintGCDetails -XX:MaxMetaspaceSize=256k?
運行結果
轉載于:https://www.cnblogs.com/qwangxiao/p/9249586.html
總結
以上是生活随笔為你收集整理的JVM从入门到放弃——JVM内存模型的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 深度学习的常用框架
- 下一篇: msp430项目编程14