国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

JVM內(nèi)存模型與運(yùn)行時(shí)數(shù)據(jù)區(qū)域

canopus4u / 2654人閱讀

摘要:內(nèi)存模型和運(yùn)行時(shí)數(shù)據(jù)區(qū)域的關(guān)系主內(nèi)存對(duì)應(yīng)著堆,工作內(nèi)存對(duì)應(yīng)著棧。在的單例模式中有運(yùn)用到二運(yùn)行時(shí)數(shù)據(jù)區(qū)域內(nèi)存區(qū)域因?yàn)榈倪\(yùn)行時(shí)數(shù)據(jù)區(qū)域一直在改善,所以不同版本之間會(huì)有不同。

一、java內(nèi)存模型

java定義內(nèi)存模型的目的是:為了屏蔽各種硬件和操作系統(tǒng)的內(nèi)存訪問(wèn)之間的差異。

java內(nèi)存模型規(guī)定了所有的變量都存儲(chǔ)在主內(nèi)存中,每條線程擁有自己的工作內(nèi)存,工作內(nèi)存保存了主內(nèi)存中變量的副本。

線程對(duì)變量操作只能在工作內(nèi)存中進(jìn)行,不能直接讀寫主內(nèi)存的變量。

不同線程之間的變量訪問(wèn)需要通過(guò)主內(nèi)存來(lái)完成。

1、java內(nèi)存模型和java運(yùn)行時(shí)數(shù)據(jù)區(qū)域的關(guān)系:主內(nèi)存對(duì)應(yīng)著java堆,工作內(nèi)存對(duì)應(yīng)著java棧。

2、volatile關(guān)鍵字,使得變量的更新在各個(gè)工作內(nèi)存中都是實(shí)時(shí)可見(jiàn)的。在DCL的單例模式中有運(yùn)用到!

二、java運(yùn)行時(shí)數(shù)據(jù)區(qū)域/內(nèi)存區(qū)域

因?yàn)閖vm的運(yùn)行時(shí)數(shù)據(jù)區(qū)域一直在改善,所以不同jdk版本之間會(huì)有不同。

1、jdk1.7之前的jvm內(nèi)存區(qū)域,擁有永久代

1、程序計(jì)數(shù)器的作用,因?yàn)?java文件被編譯成.class文件,它作為當(dāng)前線程所執(zhí)行的字節(jié)碼的行號(hào)指示器。當(dāng)字節(jié)碼解釋器工作時(shí),就是通過(guò)改變這個(gè)計(jì)算器的值來(lái)選取下一條要執(zhí)行的字節(jié)碼指令。每條線程都有一個(gè)獨(dú)立的程序計(jì)數(shù)器。

2、本地方法棧就是執(zhí)行本地native方法的棧,native方法由虛擬機(jī)實(shí)現(xiàn)!

3、java虛擬機(jī)棧描述的是該線程執(zhí)行java方法(method)時(shí)的內(nèi)存模型。每一個(gè)方法都對(duì)應(yīng)一個(gè)棧幀,棧幀中的局部變量表存儲(chǔ)了方法中的基本數(shù)據(jù)類型變量、對(duì)象引用變量。

如上圖所示,局部變量表保存了方法中聲明的8種基本類型變量和對(duì)象引用變量。每一個(gè)棧幀中還有一個(gè)指向運(yùn)行時(shí)常量池的引用,這是指String類型。下面有一個(gè)經(jīng)典的String對(duì)象生成的面試題!

4、java堆是JVM中內(nèi)存最大的一塊,被所有線程共享。幾乎所有的對(duì)象實(shí)例都在這里分配,所以java堆也是JVM垃圾回收的主要區(qū)域。java堆又被分成了年輕代,老年代;年輕代進(jìn)一步可以劃分為Eden空間,F(xiàn)rom Survivor空間、To Survivor空間。

當(dāng)我們使用new關(guān)鍵字分配對(duì)象時(shí),就是在java堆中生成對(duì)象。

下面分析一下對(duì)象生成時(shí)的情況。

因?yàn)镋den最大,所以新生成的對(duì)象都分配到Eden空間,當(dāng)Eden空間快滿時(shí),進(jìn)行一次Minor GC,然后將存活的對(duì)象復(fù)制到From Survivor空間。這時(shí),Eden空間繼續(xù)向外提供堆內(nèi)存。

后面繼續(xù)生成的對(duì)象還是放到Eden空間,當(dāng)Eden空間又要滿的時(shí)候,這時(shí)候Eden空間和From Survivor空間同時(shí)進(jìn)行一次Minor GC,然后把存活對(duì)象放到To Survivor空間。這時(shí),Eden空間繼續(xù)向外提供堆內(nèi)存。

接下來(lái)的情況和2一致。Eden空間快滿的時(shí)候,Eden空間和To Survivor空間進(jìn)行一次Minor GC,然后存活的對(duì)象放到From Survivor空間。

接下來(lái)的情況和3一致。Eden空間快慢的時(shí)候,Eden空間和From Survivor空間進(jìn)行一次Minor GC,然后存活的對(duì)象放到To Survivor空間。

就是說(shuō)2個(gè)Survivor中的一個(gè)用來(lái)提供對(duì)象保存。當(dāng)Eden空間和某一塊Survivor空間GC后,另一塊Survivor空間放不下GC后存活的對(duì)象;或者是連續(xù)Minor GC15次左右的情況;就把這部分存活對(duì)象放入到老年代空間。

當(dāng)老年代空間也放滿的時(shí)候,進(jìn)行Major GC,對(duì)老年代空間進(jìn)行回收。(也叫做Full GC,F(xiàn)ull GC的內(nèi)存消耗很大,應(yīng)該避免)

年輕代使用的是復(fù)制算法:每次Minor GC把Eden區(qū)和一塊Survivor區(qū)的存活對(duì)象復(fù)制到另一塊Survivor區(qū)。老年代使用的是標(biāo)記-整理算法:每次Major GC把存活對(duì)象都想內(nèi)存空間的一端移動(dòng),然后直接清理掉端邊界以外的內(nèi)存。

大對(duì)象如數(shù)組、很長(zhǎng)的字符串,直接進(jìn)入老年代空間。

5、方法區(qū)用于存儲(chǔ)JVM加載的類信息、final常量、static靜態(tài)變量等數(shù)據(jù),方法區(qū)中的數(shù)據(jù)都是整個(gè)程序中唯一的。方法區(qū)還包含了運(yùn)行時(shí)常量池,主要存放編譯期生成的字面量和符號(hào)引用(在類加載后放入)。String對(duì)象的字面量就會(huì)被放入到運(yùn)行時(shí)常量池中。

垃圾回收在方法區(qū)主要是對(duì)常量的回收和對(duì)類型的卸載。

2、jdk1.8及之后的jvm內(nèi)存區(qū)域,元空間取代了永久代

參考文章:java8的jvm內(nèi)存區(qū)域。

元空間和永久代的性質(zhì)是一樣的,都是對(duì)JVM方法區(qū)的實(shí)現(xiàn),作用是一樣的。不過(guò)元空間與永久代之間最大的區(qū)別在于:元空間并不在虛擬機(jī)JVM內(nèi)存中,而是使用本地內(nèi)存。

為什么用元空間取代永久代呢?

字符串存在永久代中,容易出現(xiàn)性能問(wèn)題和內(nèi)存溢出。

類及方法的信息等比較難確定其大小,因此對(duì)于永久代的大小指定比較困難,太小容易出現(xiàn)永久代溢出,太大則容易導(dǎo)致老年代溢出。

永久代會(huì)為GC帶來(lái)不必要的復(fù)雜度,并且回收效率偏低。

直接內(nèi)存

JDK1.4之后加入的NIO,引入了基于通道channel和緩沖區(qū)buffer的IO,直接使用native函數(shù)分配堆外內(nèi)存,顯著提高IO性能,避免了原來(lái)BIO的在java堆和naive堆中來(lái)回復(fù)制數(shù)據(jù)。

3、字符串String生成時(shí)的內(nèi)存分配情況

參考文章:字符串常量池。

4、生成對(duì)象時(shí)的內(nèi)存情況

下面來(lái)分析一下我們常見(jiàn)的生成對(duì)象或基本數(shù)據(jù)類型變量的內(nèi)存模型。這樣可以對(duì)JVM有一個(gè)更好的理解。

int i =3;,一個(gè)方法對(duì)應(yīng)一個(gè)棧幀,方法中的基本數(shù)據(jù)類型變量直接在棧幀中分配。如果是static、final類型的基本數(shù)據(jù)類型則存儲(chǔ)在運(yùn)行時(shí)常量池中,和String一樣

Object o1 = new Object();,對(duì)象引用(Object o1)存儲(chǔ)在棧幀中,但是對(duì)象數(shù)據(jù)(new Object())存儲(chǔ)在java堆中,對(duì)象類型數(shù)據(jù)(Class等信息)存儲(chǔ)在方法區(qū)中。

String s1 = new String("abcd");,使用new聲明的對(duì)象,對(duì)象引用(String s1)存儲(chǔ)在棧幀中,對(duì)象數(shù)據(jù)(new String(“abcd”))存儲(chǔ)在java堆中,字符串值(“abcd”)存儲(chǔ)在運(yùn)行時(shí)常量池中。

String s2 = “abc”,對(duì)象引用(String s2)存儲(chǔ)在棧幀中,字符串值(“abc”)存儲(chǔ)在運(yùn)行時(shí)常量池中。

java棧、java堆、方法區(qū)這3者之間的關(guān)系大概就是上面的分析所示。

3、各種異常分析 1、java堆內(nèi)存溢出錯(cuò)誤OutOfMemoryError

如果java堆中分配的對(duì)象太多,且GC后內(nèi)存空間還是不夠用。下面通過(guò)循環(huán)生成對(duì)象來(lái)消耗內(nèi)存空間進(jìn)行測(cè)試。

相關(guān)指令:VM Args: -Xms20m -Xmx40m,表示JVM分配的堆內(nèi)存最小為20MB,最大為40MB。

 public static void main(String[] args) {
   while (true) {
     List list = new ArrayList<>(10);
     list.add(new Object());
   }
 }
2、java棧堆棧溢出錯(cuò)誤StackoverflowError

如果java棧的棧深度大于JVM允許的深度,就會(huì)拋出該錯(cuò)誤。下面通過(guò)無(wú)限遞歸調(diào)用來(lái)進(jìn)行堆棧進(jìn)行測(cè)試。

相關(guān)指令:VM Args: -Xss128k,表示JVM分配的棧容量為128KB。

public class StackOOM {
    
    private int length = 1;
    
    public void stackLeak() {
        length++;
        stackLeak();
    }
    
    public static void main(String[] args) {
        StackOOM stackOOM = new StackOOM();
        stackOOM.stackLeak();
    }
}

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/71684.html

相關(guān)文章

  • JVM內(nèi)存模型

    摘要:的內(nèi)存模型概述虛擬機(jī)在執(zhí)行程序的過(guò)程中,會(huì)把它所管理的內(nèi)存劃分為若干個(gè)不同的數(shù)據(jù)區(qū)域。程序計(jì)數(shù)器這是一塊較小的內(nèi)存,它可以看做是當(dāng)前線程所執(zhí)行的字節(jié)碼的行號(hào)指示器。 JVM的內(nèi)存模型 概述 Java虛擬機(jī)在執(zhí)行java程序的過(guò)程中,會(huì)把它所管理的內(nèi)存劃分為若干個(gè)不同的數(shù)據(jù)區(qū)域。這些區(qū)域都有各自的用途,以及創(chuàng)建和銷毀的時(shí)間,有的區(qū)域隨著虛擬機(jī)進(jìn)程的啟動(dòng)而存在,有些區(qū)域則依賴用戶線程的啟動(dòng)...

    andycall 評(píng)論0 收藏0
  • JVM運(yùn)行時(shí)數(shù)據(jù)區(qū)域

    摘要:虛擬機(jī)在執(zhí)行程序的過(guò)程中會(huì)把它所管理的內(nèi)存劃分為若干個(gè)不同的數(shù)據(jù)區(qū)域,本篇文章將會(huì)對(duì)這些數(shù)據(jù)區(qū)域進(jìn)行簡(jiǎn)略的介紹。運(yùn)行時(shí)常量池運(yùn)行時(shí)常量池是方法區(qū)的一部分。直接內(nèi)存直接內(nèi)存不是虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū)的一部分,不是虛擬機(jī)規(guī)范中定義的內(nèi)存區(qū)域。 Java虛擬機(jī)在執(zhí)行Java程序的過(guò)程中會(huì)把它所管理的內(nèi)存劃分為若干個(gè)不同的數(shù)據(jù)區(qū)域,本篇文章將會(huì)對(duì)這些數(shù)據(jù)區(qū)域進(jìn)行簡(jiǎn)略的介紹。JVM所管理的內(nèi)存包括的...

    meislzhua 評(píng)論0 收藏0
  • JVM 內(nèi)存模型

    摘要:是描述方法執(zhí)行的內(nèi)存模型每個(gè)方法執(zhí)行的時(shí)候會(huì)同時(shí)創(chuàng)建一個(gè)棧幀,用于存儲(chǔ)局部變量表操作數(shù)棧動(dòng)態(tài)連接返回地址方法出口等信息。虛擬機(jī)是使用局部變量表完成參數(shù)值到參數(shù)變量表的傳遞過(guò)程。堆內(nèi)存管理最大的一塊。 showImg(https://segmentfault.com/img/bVLqsv?w=475&h=398); 1. 虛擬機(jī)棧 VM Stack 線程私有,生命周期與線程相同。VM S...

    SexySix 評(píng)論0 收藏0
  • JVM 的 工作原理,層次結(jié)構(gòu) 以及 GC工作原理

    摘要:執(zhí)行引擎作用執(zhí)行字節(jié)碼,或者執(zhí)行本地方法運(yùn)行時(shí)數(shù)據(jù)區(qū)其實(shí)就是指在運(yùn)行期間,其對(duì)內(nèi)存空間的劃分和分配。 雖是讀書筆記,但是如轉(zhuǎn)載請(qǐng)注明出處https://uestc-dpz.github.io..拒絕伸手復(fù)制黨 JVM Java 虛擬機(jī) Java 虛擬機(jī)(Java virtual machine,JVM)是運(yùn)行 Java 程序必不可少的機(jī)制。JVM實(shí)現(xiàn)了Java語(yǔ)言最重要的特征:即平臺(tái)...

    qqlcbb 評(píng)論0 收藏0
  • JVM 探究(一):JVM內(nèi)存模型概念模型

    摘要:作為一個(gè)程序員,不了解內(nèi)存模型就不能寫出能夠充分利用內(nèi)存的代碼。程序計(jì)數(shù)器是在電腦處理器中的一個(gè)寄存器,用來(lái)指示電腦下一步要運(yùn)行的指令序列。在虛擬機(jī)中,本地方法棧和虛擬機(jī)棧是共用同一塊內(nèi)存的,不做具體區(qū)分。 作為一個(gè) Java 程序員,不了解 Java 內(nèi)存模型就不能寫出能夠充分利用內(nèi)存的代碼。本文通過(guò)對(duì) Java 內(nèi)存模型的介紹,讓讀者能夠了解 Java 的內(nèi)存的分配情況,適合 Ja...

    cnTomato 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<