日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

JVM从入门到放弃——JVM内存模型

發(fā)布時間:2025/3/15 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JVM从入门到放弃——JVM内存模型 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前言

Java和C或者是C++相比較而言,最大的區(qū)別是C系列的程序員在編寫代碼的時候,總是要對程序中的變量進(jìn)行釋放內(nèi)存的操作,所以在編寫C或者是C++的程序員需要格外的謹(jǐn)慎,因?yàn)樗麄儗Τ绦虻膬?nèi)存有著很高的權(quán)限,這樣雖然是特點(diǎn)但是同時也是缺點(diǎn),畢竟every coin has two sides。所以跟Java語言相比而言,Java把內(nèi)存的管理直接交付給JVM,因?yàn)镴VM的存在,Java程序員能夠更關(guān)注業(yè)務(wù)的實(shí)現(xiàn),而不需要對內(nèi)存的管理過于關(guān)注。但是我們在編程的時候,有時候會出現(xiàn)OutOfMemoryError之類的錯誤,這就是JVM內(nèi)存溢出的錯誤。這樣如果我們對Java虛擬機(jī)對內(nèi)存的管理,我們就不能很好的解決類似的問題,所以我們還是要對Java的內(nèi)存管理要有一定的理解,對我們后期對Java代碼調(diào)優(yōu)也是有一定的幫助。

Java虛擬機(jī)內(nèi)存模型

?
根據(jù)上圖可以看出來JVM的運(yùn)行時數(shù)據(jù)區(qū)域主要就是方法區(qū),虛擬機(jī)棧,虛擬機(jī)堆內(nèi)存,本地方法區(qū)和程序計(jì)數(shù)器。下面就來看看這些個內(nèi)存區(qū)域都是用來存儲哪些數(shù)據(jù)的。

Java虛擬機(jī)棧

方法區(qū)是線程私有的內(nèi)存區(qū)域,聲明周期與線程相同。虛擬機(jī)棧描述的是Java方法執(zhí)行的內(nèi)存模型,每個方法執(zhí)行的時候,虛擬機(jī)會以棧幀的形式壓入到棧中,這里的棧也是一種先進(jìn)后出的數(shù)據(jù)結(jié)構(gòu)。棧幀通常是用來存儲局部變量表,操作數(shù)棧,幀數(shù)據(jù)區(qū)等信息。每個方法的調(diào)用和結(jié)束都是入棧和出棧的操作。由于每次方法的調(diào)用都會生成對應(yīng)的棧幀,棧幀會占用一定的棧空間,因此,如果棧幀的空間不足,函數(shù)的調(diào)用就無法進(jìn)行下去,當(dāng)請求的棧的深度大于最大的可用棧深度的時候,系統(tǒng)就會拋出StackOverflowError的溢出錯誤。?
局部變量表存放編譯期可以知道的各種基本數(shù)據(jù)類型(boolean,byte,char,short,int,float,long,double),對象引用和returnAddress類型。其中64位長度的long和double類型的數(shù)據(jù)會占用2個slot局部變量空間,其余的都是一個slot。局部變量表所需要的內(nèi)存空間在編譯期間完成分配,運(yùn)行期間不會改變局部變量表的大小。?
代碼實(shí)現(xiàn)StackOverflowError的溢出錯誤

package com.jvm.method_region;public class MethodRegionTest {Integer count = 0;public void method1() { count ++; method1(); } public static void main(String[] args) { MethodRegionTest methodRegionTest = null; try { methodRegionTest = new MethodRegionTest(); methodRegionTest.method1(); }catch (Exception e) { // TODO: handle exception }finally { System.out.println("遞歸java棧的深度是 : " + methodRegionTest.count);

在運(yùn)行的時候,修改JVM參數(shù),通過修改-Xss128K可以改變虛擬機(jī)棧的大小,我第一次是128K第二次是256K,看執(zhí)行的結(jié)果

遞歸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的參數(shù)操作?
?
<————————-這是分隔符————————————->?

本地方法棧

本地方法棧和虛擬機(jī)棧類似,但是他們也是有區(qū)別的,區(qū)別就是虛擬機(jī)棧是調(diào)用java方法的時候,會把棧幀壓入棧中,而本地方法棧是調(diào)用的native方法,native是由C++編寫的。同時本地方法棧也會和虛擬機(jī)棧一樣也是會爆出來StackOverflowError和OutOfMemoryError的錯誤。OutOfMemoryError的錯誤是在虛擬機(jī)的棧內(nèi)存可以自動擴(kuò)展的情況下,不停的將棧幀數(shù)據(jù)壓入到棧中,以至于虛擬機(jī)不停的申請內(nèi)存,最后導(dǎo)致內(nèi)存的溢出,所以爆出來OutOfMemoryError錯誤。

虛擬機(jī)堆

Java Heap是Java虛擬機(jī)所管理的內(nèi)存最大的一塊,這一塊的內(nèi)存區(qū)域是所有線程共享的。此內(nèi)存區(qū)域是用來存放對象實(shí)例,幾乎所有的對象實(shí)例以及數(shù)組都在這里分配內(nèi)存。Java Heap還可以細(xì)分為新生代區(qū)和老年代區(qū),而新生代區(qū)還可以分為eden區(qū),from區(qū)和to區(qū),from和to的大小是一樣的。在絕大數(shù)的情況下,對象是先分配在eden區(qū),在第一次垃圾回收后,如果對象還存活著,那么該對象就會進(jìn)入到from區(qū)或者是to區(qū),然后每經(jīng)過一次垃圾回收,對象依然存活著,它的年紀(jì)就會增加1。當(dāng)對象的年紀(jì)到達(dá)一定的條件后,該對象就會進(jìn)入到老年tenured區(qū)。

程序計(jì)數(shù)器

Program Counter是每個線程的私有空間,Java虛擬機(jī)會為每一個線程創(chuàng)建PC寄存器,在任意時刻,一個線程總是在執(zhí)行一個方法,正在執(zhí)行的方法稱為當(dāng)前方法。如果當(dāng)前方法不是本地方法,PC寄存器就會指向當(dāng)前正在被執(zhí)行的指令。如果當(dāng)前方法是本地方法,那么PC寄存器的值就是undefined。

方法區(qū)

方法區(qū)也是線程共享的內(nèi)存區(qū)域,用于保存系統(tǒng)的類信息,比如類的字段,方法,常量池等,方法區(qū)的大小決定了系統(tǒng)可以保存多少個類如果系統(tǒng)定義了太多的類,同樣會導(dǎo)致方法區(qū)的溢出。在JDK1.6和JDK1.7中,方法區(qū)可以理解為永久區(qū)(Perm)。永久區(qū)可以使用參數(shù)-XX:PermSize和-XX:MaxPermSize指定,默認(rèn)情況下,-XX:MaxPermSize為64MB。一個大的永久區(qū)可以保存更多的信息。如果系統(tǒng)中使用一些動態(tài)代理,那么就有可能在運(yùn)行時生成大量的類。在JDK1.8中,永久區(qū)已經(jīng)被徹底移除,用元數(shù)據(jù)區(qū)來代替。元數(shù)據(jù)區(qū)可以使用-XX:MaxMetaspaceSize指定,元數(shù)據(jù)區(qū)使用的系統(tǒng)的直接內(nèi)存。如果不指定元數(shù)據(jù)的大小,程序會耗盡所有的內(nèi)存。

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

加了虛擬機(jī)參數(shù)-XX:+PrintGCDetails -XX:MaxMetaspaceSize=256k?
運(yùn)行結(jié)果

Error occurred during initialization of VM OutOfMemoryError: Metaspace

轉(zhuǎn)載于:https://www.cnblogs.com/qwangxiao/p/9249586.html

總結(jié)

以上是生活随笔為你收集整理的JVM从入门到放弃——JVM内存模型的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。