最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JAVA內(nèi)存區(qū)域示例詳解

 更新時(shí)間:2025年12月27日 09:39:45   作者:此時(shí)已鶯飛草長(zhǎng)  
Java內(nèi)存區(qū)域包括程序計(jì)數(shù)器、虛擬機(jī)棧、本地方法棧、堆、元空間和直接內(nèi)存,分別用于線程私有數(shù)據(jù)和線程共享數(shù)據(jù),理解這些區(qū)域有助于定位內(nèi)存問(wèn)題、優(yōu)化JVM性能和編寫高性能代碼,本文介紹java內(nèi)存區(qū)域的相關(guān)知識(shí),感興趣的朋友一起看看吧

一、Java內(nèi)存區(qū)域的核心定義

Java內(nèi)存區(qū)域(也叫「JVM運(yùn)行時(shí)數(shù)據(jù)區(qū)」)是 Java虛擬機(jī)(JVM)在運(yùn)行Java程序時(shí),對(duì)內(nèi)存的結(jié)構(gòu)化劃分 —— JVM將申請(qǐng)到的內(nèi)存拆分成多個(gè)功能明確、邊界清晰的區(qū)域,每個(gè)區(qū)域負(fù)責(zé)存儲(chǔ)特定類型的數(shù)據(jù),并有專屬的內(nèi)存分配、回收規(guī)則和生命周期。

核心目的:精細(xì)化管理內(nèi)存(避免內(nèi)存混亂、提升分配/回收效率),同時(shí)隔離不同類型數(shù)據(jù)的生命周期(比如線程私有數(shù)據(jù)隨線程銷毀,共享數(shù)據(jù)統(tǒng)一回收)。

?? 關(guān)鍵澄清:
很多人會(huì)混淆「Java內(nèi)存區(qū)域」和之前講的「Java內(nèi)存模型(JMM)」,兩者完全不同:

維度Java內(nèi)存區(qū)域(JVM運(yùn)行時(shí)數(shù)據(jù)區(qū))Java內(nèi)存模型(JMM)
本質(zhì)物理內(nèi)存的「功能劃分」(存儲(chǔ)結(jié)構(gòu))抽象規(guī)范(解決多線程內(nèi)存一致性問(wèn)題)
關(guān)注對(duì)象內(nèi)存“存什么、在哪存、何時(shí)回收”多線程“如何安全訪問(wèn)共享變量”
核心目標(biāo)內(nèi)存分配與回收保證并發(fā)的可見(jiàn)性、原子性、有序性

二、Java內(nèi)存區(qū)域的整體結(jié)構(gòu)(JDK 8+)

JVM規(guī)范將內(nèi)存區(qū)域分為「線程私有區(qū)域」和「線程共享區(qū)域」,JDK 8是重要分界點(diǎn)(移除永久代,改用元空間),以下基于JDK 8及以后版本講解:

Java內(nèi)存區(qū)域
├── 線程私有區(qū)域(每個(gè)線程獨(dú)立擁有,隨線程銷毀)
│   ├── 程序計(jì)數(shù)器
│   ├── 虛擬機(jī)棧(Java棧)
│   └── 本地方法棧
├── 線程共享區(qū)域(所有線程共用,隨JVM啟動(dòng)/銷毀)
│   ├── 堆(Java Heap)
│   └── 元空間(Metaspace,替代JDK7的永久代)
└── 直接內(nèi)存(Direct Memory,非JVM規(guī)范定義,堆外內(nèi)存)

三、逐個(gè)解析:每個(gè)內(nèi)存區(qū)域的作用、內(nèi)容與問(wèn)題

1. 程序計(jì)數(shù)器(Program Counter Register)

核心理解

可以看作「線程的執(zhí)行進(jìn)度條」—— 記錄當(dāng)前線程正在執(zhí)行的Java字節(jié)碼指令的地址(或本地方法的執(zhí)行地址),線程切換后能通過(guò)計(jì)數(shù)器恢復(fù)執(zhí)行位置。

關(guān)鍵特性

  • 線程私有:每個(gè)線程有獨(dú)立的程序計(jì)數(shù)器,避免線程間干擾;
  • 無(wú)OOM:是JVM內(nèi)存區(qū)域中唯一不會(huì)拋出 OutOfMemoryError(OOM)的區(qū)域;
  • 存儲(chǔ)內(nèi)容
    • 執(zhí)行Java方法時(shí):存儲(chǔ)當(dāng)前字節(jié)碼指令的行號(hào)(通過(guò)pc寄存器記錄);
    • 執(zhí)行Native方法(如C/C++實(shí)現(xiàn)的方法)時(shí):計(jì)數(shù)器值為undefined(本地方法由操作系統(tǒng)調(diào)度,JVM不跟蹤)。

示例理解

比如線程A執(zhí)行到main方法的第10行代碼,程序計(jì)數(shù)器記錄“第10行對(duì)應(yīng)的字節(jié)碼地址”;此時(shí)CPU切換到線程B執(zhí)行,線程A暫停;當(dāng)CPU切回線程A時(shí),通過(guò)計(jì)數(shù)器找到之前的地址,繼續(xù)從第10行執(zhí)行。

2. 虛擬機(jī)棧(Java Virtual Machine Stack)

核心理解

Java方法執(zhí)行提供內(nèi)存空間 —— 每個(gè)Java方法被調(diào)用時(shí),JVM會(huì)為該方法創(chuàng)建一個(gè)「棧幀(Stack Frame)」,棧幀入棧;方法執(zhí)行完成后,棧幀出棧。虛擬機(jī)棧的生命周期與線程完全一致。

棧幀的核心內(nèi)容(方法的“內(nèi)存快照”)

每個(gè)棧幀包含4部分,是方法執(zhí)行的核心內(nèi)存載體:

棧幀組成作用
局部變量表存儲(chǔ)方法的局部變量(基本類型、對(duì)象引用、returnAddress類型),容量固定
操作數(shù)棧方法執(zhí)行時(shí)的臨時(shí)運(yùn)算空間(比如執(zhí)行a+b時(shí),先壓入a、b,再?gòu)棾鲇?jì)算)
動(dòng)態(tài)鏈接指向運(yùn)行時(shí)常量池的引用(比如方法調(diào)用時(shí)解析符號(hào)引用為直接引用)
方法出口記錄方法執(zhí)行完成后返回的位置(比如回到調(diào)用方的哪一行)

關(guān)鍵特性與問(wèn)題

  • 線程私有:每個(gè)線程有獨(dú)立的虛擬機(jī)棧,互不干擾;
  • 大小限制:棧的容量可通過(guò)-Xss參數(shù)設(shè)置(如-Xss1M,默認(rèn)約1M);
  • 常見(jiàn)異常
    • StackOverflowError:棧深度超出限制(比如無(wú)限遞歸調(diào)用方法,棧幀不斷入棧,撐滿棧);
    • OutOfMemoryError:虛擬機(jī)棧支持動(dòng)態(tài)擴(kuò)展時(shí),擴(kuò)展內(nèi)存不足(極少發(fā)生,主流JVM棧容量固定)。

代碼示例:觸發(fā)StackOverflowError

/**
 * 無(wú)限遞歸調(diào)用,虛擬機(jī)棧幀不斷入棧,觸發(fā)棧溢出
 */
public class StackOverflowDemo {
    private static int depth = 0;
    public static void recursive() {
        depth++;
        recursive(); // 無(wú)限遞歸,棧幀持續(xù)入棧
    }
    public static void main(String[] args) {
        try {
            recursive();
        } catch (StackOverflowError e) {
            System.out.println("遞歸深度:" + depth);
            System.out.println("異常:" + e);
        }
    }
}

執(zhí)行結(jié)果(示例):

遞歸深度:10886
異常:java.lang.StackOverflowError

解釋:每次調(diào)用recursive()都會(huì)創(chuàng)建新棧幀,直到虛擬機(jī)棧被撐滿,拋出棧溢出異常。

3. 本地方法棧(Native Method Stack)

核心理解

與虛擬機(jī)棧功能類似,但專為Native方法(非Java語(yǔ)言實(shí)現(xiàn)的方法,如C/C++方法)提供內(nèi)存支持

關(guān)鍵特性

  • 線程私有:每個(gè)線程有獨(dú)立的本地方法棧;
  • 存儲(chǔ)內(nèi)容:Native方法的執(zhí)行狀態(tài)(如局部變量、寄存器狀態(tài)等);
  • 常見(jiàn)異常:和虛擬機(jī)棧一致,會(huì)拋出StackOverflowErrorOutOfMemoryError;
  • 示例:Java中的Object.hashCode()System.arraycopy()等方法底層是Native實(shí)現(xiàn),執(zhí)行時(shí)會(huì)用到本地方法棧。

4. 堆(Java Heap)

核心理解

JVM中最大的內(nèi)存區(qū)域,唯一目的是存儲(chǔ)「對(duì)象實(shí)例和數(shù)組」(幾乎所有對(duì)象都分配在堆上),是垃圾回收(GC)的核心戰(zhàn)場(chǎng) —— 我們常說(shuō)的“GC回收內(nèi)存”,主要就是回收堆中不再被引用的對(duì)象。

關(guān)鍵特性

  • 線程共享:所有線程共用堆內(nèi)存,因此多線程創(chuàng)建對(duì)象時(shí)需考慮線程安全;
  • 生命周期:JVM啟動(dòng)時(shí)創(chuàng)建,JVM退出時(shí)銷毀;
  • 堆的細(xì)分(GC優(yōu)化)
    為了提升GC效率,堆被進(jìn)一步劃分為「新生代」和「老年代」(比例默認(rèn)1:2,可通過(guò)-XX:NewRatio調(diào)整):
    堆
    ├── 新生代(Young Generation):存儲(chǔ)新創(chuàng)建的對(duì)象(短命對(duì)象)
    │   ├── Eden區(qū)(伊甸園區(qū)):新對(duì)象優(yōu)先分配到這里
    │   ├── Survivor0區(qū)(S0,F(xiàn)rom區(qū))
    │   └── Survivor1區(qū)(S1,To區(qū))
    └── 老年代(Old Generation):存儲(chǔ)存活時(shí)間長(zhǎng)的對(duì)象(長(zhǎng)命對(duì)象)
    • 新生代GC(Minor GC):Eden區(qū)滿時(shí)觸發(fā),回收短命對(duì)象,頻率高、速度快;
    • 老年代GC(Major GC/Full GC):老年代滿時(shí)觸發(fā),回收長(zhǎng)命對(duì)象,頻率低、速度慢(會(huì)引發(fā)STW,影響性能)。

常見(jiàn)問(wèn)題

  • OutOfMemoryError: Java heap space:堆內(nèi)存不足(比如創(chuàng)建大量大對(duì)象且不釋放引用,堆被占滿)。

代碼示例:觸發(fā)堆溢出

import java.util.ArrayList;
import java.util.List;
/**
 * 不斷創(chuàng)建大對(duì)象并保存引用,堆內(nèi)存被占滿,觸發(fā)OOM
 */
public class HeapOOMDemo {
    // 大對(duì)象:占用100KB內(nèi)存
    static class BigObject {
        private byte[] data = new byte[1024 * 100];
    }
    public static void main(String[] args) {
        List<BigObject> list = new ArrayList<>();
        try {
            while (true) {
                list.add(new BigObject()); // 保存對(duì)象引用,無(wú)法GC
            }
        } catch (OutOfMemoryError e) {
            System.out.println("堆溢出:" + e);
        }
    }
}

運(yùn)行時(shí)添加JVM參數(shù)(限制堆大?。?code>-Xms20m -Xmx20m(初始堆20M,最大堆20M),執(zhí)行結(jié)果:

堆溢出:java.lang.OutOfMemoryError: Java heap space

解釋:不斷創(chuàng)建BigObject并加入List,對(duì)象無(wú)法被GC回收,堆內(nèi)存被占滿,拋出堆溢出異常。

5. 元空間(Metaspace,JDK 8+)

核心理解

替代JDK 7及以前的「永久代(PermGen)」,用于存儲(chǔ)類的元數(shù)據(jù)(類的結(jié)構(gòu)信息、方法信息、常量池、靜態(tài)變量、注解等)。

關(guān)鍵特性

  • 線程共享:所有線程共用元空間;
  • 內(nèi)存來(lái)源:元空間使用「本地內(nèi)存」(操作系統(tǒng)的內(nèi)存),而非JVM堆內(nèi)存(永久代使用堆內(nèi)存),因此默認(rèn)情況下元空間大小受操作系統(tǒng)內(nèi)存限制;
  • 可配置:可通過(guò)-XX:MetaspaceSize(初始大?。?code>-XX:MaxMetaspaceSize(最大大?。┫拗圃臻g;
  • GC回收:當(dāng)類被卸載(如自定義類加載器加載的類)時(shí),元空間會(huì)回收該類的元數(shù)據(jù)。

常見(jiàn)問(wèn)題

  • OutOfMemoryError: Metaspace:元空間不足(比如動(dòng)態(tài)生成大量類,如反射、動(dòng)態(tài)代理、CGLIB等,元數(shù)據(jù)占滿)。

代碼示例:觸發(fā)元空間溢出

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
/**
 * 動(dòng)態(tài)生成大量類,元空間被占滿,觸發(fā)OOM(需引入CGLIB依賴)
 */
public class MetaspaceOOMDemo {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        try {
            while (true) {
                // 動(dòng)態(tài)生成匿名子類
                enhancer.setSuperclass(Object.class);
                enhancer.setCallback((MethodInterceptor) (obj, method, args1, proxy) -> proxy.invokeSuper(obj, args1));
                enhancer.create(); // 生成新類,元數(shù)據(jù)存入元空間
            }
        } catch (OutOfMemoryError e) {
            System.out.println("元空間溢出:" + e);
        }
    }
}

運(yùn)行時(shí)添加JVM參數(shù):-XX:MaxMetaspaceSize=10m(限制元空間最大10M),執(zhí)行結(jié)果:

元空間溢出:java.lang.OutOfMemoryError: Metaspace

解釋:CGLIB不斷動(dòng)態(tài)生成新類,類的元數(shù)據(jù)占滿元空間,拋出元空間溢出異常。

6. 直接內(nèi)存(Direct Memory)

核心理解

不屬于JVM規(guī)范定義的內(nèi)存區(qū)域(是“堆外內(nèi)存”),但被頻繁使用 —— JVM通過(guò)Unsafe類或ByteBuffer.allocateDirect()分配直接內(nèi)存,用于提升IO性能(避免JVM堆和操作系統(tǒng)內(nèi)存之間的拷貝)。

關(guān)鍵特性

  • 內(nèi)存來(lái)源:操作系統(tǒng)的本地內(nèi)存,不受JVM堆大小限制(但受總物理內(nèi)存限制);
  • 訪問(wèn)速度:比堆內(nèi)存快(減少內(nèi)存拷貝),但分配/回收成本更高;
  • 常見(jiàn)問(wèn)題OutOfMemoryError: Direct buffer memory(直接內(nèi)存不足)。

示例:分配直接內(nèi)存

import java.nio.ByteBuffer;
/**
 * 分配大量直接內(nèi)存,觸發(fā)直接內(nèi)存溢出
 */
public class DirectMemoryOOMDemo {
    public static void main(String[] args) {
        int size = 1024 * 1024 * 100; // 100MB
        try {
            while (true) {
                // 分配直接內(nèi)存
                ByteBuffer buffer = ByteBuffer.allocateDirect(size);
            }
        } catch (OutOfMemoryError e) {
            System.out.println("直接內(nèi)存溢出:" + e);
        }
    }
}

運(yùn)行時(shí)添加JVM參數(shù):-XX:MaxDirectMemorySize=200m(限制直接內(nèi)存最大200M),執(zhí)行結(jié)果:

直接內(nèi)存溢出:java.lang.OutOfMemoryError: Direct buffer memory

四、關(guān)鍵對(duì)比:線程私有 vs 線程共享區(qū)域

類型包含區(qū)域生命周期核心特點(diǎn)
線程私有程序計(jì)數(shù)器、虛擬機(jī)棧、本地方法棧與線程一致(線程創(chuàng)建則創(chuàng)建,線程銷毀則銷毀)無(wú)需GC回收(隨線程銷毀自動(dòng)釋放)
線程共享堆、元空間與JVM一致(JVM啟動(dòng)則創(chuàng)建,退出則銷毀)需GC回收(堆回收對(duì)象,元空間回收類元數(shù)據(jù))

五、理解Java內(nèi)存區(qū)域的核心意義

  1. 定位內(nèi)存問(wèn)題:不同的內(nèi)存異常對(duì)應(yīng)不同的區(qū)域(比如StackOverflowError是棧問(wèn)題,Java heap space是堆問(wèn)題),理解內(nèi)存區(qū)域能快速定位問(wèn)題根源;
  2. 優(yōu)化JVM性能:通過(guò)調(diào)整各區(qū)域的內(nèi)存參數(shù)(如-Xms/-Xmx調(diào)整堆大小,-Xss調(diào)整棧大?。?,適配業(yè)務(wù)場(chǎng)景,減少GC頻率和OOM概率;
  3. 理解GC原理:GC的核心是回收堆內(nèi)存,而堆的分代設(shè)計(jì)(新生代/老年代)直接影響GC策略,理解內(nèi)存區(qū)域是掌握GC的基礎(chǔ);
  4. 編寫高性能代碼:比如避免創(chuàng)建大量短命大對(duì)象(減少M(fèi)inor GC)、避免無(wú)限遞歸(防止棧溢出)、合理使用直接內(nèi)存(提升IO性能)。

六、總結(jié)

Java內(nèi)存區(qū)域是JVM對(duì)運(yùn)行時(shí)內(nèi)存的“功能分區(qū)管理”,核心是:

  • 線程私有區(qū)域?yàn)榫€程執(zhí)行提供基礎(chǔ)(程序計(jì)數(shù)器記錄執(zhí)行位置,棧為方法提供內(nèi)存);
  • 線程共享區(qū)域存儲(chǔ)共享數(shù)據(jù)(堆存對(duì)象,元空間存類信息);
  • 直接內(nèi)存是堆外優(yōu)化手段,提升IO性能。

理解每個(gè)區(qū)域的“存儲(chǔ)內(nèi)容、生命周期、異常類型”,是排查JVM內(nèi)存問(wèn)題、優(yōu)化JVM性能的核心基礎(chǔ)。

到此這篇關(guān)于JAVA內(nèi)存區(qū)域示例詳解的文章就介紹到這了,更多相關(guān)java內(nèi)存區(qū)域內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot前后端分離實(shí)現(xiàn)個(gè)人博客系統(tǒng)

    SpringBoot前后端分離實(shí)現(xiàn)個(gè)人博客系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了使用springboot+mybatis+前端vue,使用前后端分離架構(gòu)實(shí)現(xiàn)的個(gè)人博客系統(tǒng),感興趣的小伙伴可以動(dòng)手嘗試一下
    2022-06-06
  • linux環(huán)境下java程序打包成簡(jiǎn)單的hello world輸出jar包示例

    linux環(huán)境下java程序打包成簡(jiǎn)單的hello world輸出jar包示例

    這篇文章主要介紹了linux環(huán)境下java程序打包成簡(jiǎn)單的hello world輸出jar包,結(jié)合簡(jiǎn)單hello world輸出程序示例分析了Linux環(huán)境下的java可執(zhí)行jar包文件的生成相關(guān)操作技巧,需要的朋友可以參考下
    2019-11-11
  • MyBatis-plus中的模糊查詢解讀

    MyBatis-plus中的模糊查詢解讀

    這篇文章主要介紹了MyBatis-plus中的模糊查詢解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • 對(duì)Java字符串與整形、浮點(diǎn)類型之間的相互轉(zhuǎn)換方法總結(jié)

    對(duì)Java字符串與整形、浮點(diǎn)類型之間的相互轉(zhuǎn)換方法總結(jié)

    今天小編就為大家分享一篇對(duì)Java字符串與整形、浮點(diǎn)類型之間的相互轉(zhuǎn)換方法總結(jié),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-07-07
  • Java自定義Enum的實(shí)現(xiàn)示例

    Java自定義Enum的實(shí)現(xiàn)示例

    Java中的自定義Enum類型是一種特殊的類,用于表示固定數(shù)量的常量值,本文主要介紹了Java自定義Enum的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-12-12
  • struts2框架的登錄制作圖文教程

    struts2框架的登錄制作圖文教程

    下面小編就為大家?guī)?lái)一篇struts2框架的登錄制作圖文教程。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-11-11
  • 使用Sharding-JDBC對(duì)數(shù)據(jù)進(jìn)行分片處理詳解

    使用Sharding-JDBC對(duì)數(shù)據(jù)進(jìn)行分片處理詳解

    這篇文章主要介紹了使用Sharding-JDBC對(duì)數(shù)據(jù)進(jìn)行分片處理詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • Java中的Semaphore如何使用

    Java中的Semaphore如何使用

    Semaphore實(shí)際上是一種共享鎖,因?yàn)樗试S多個(gè)線程并發(fā)獲取共享的資源,在Semaphore對(duì)象創(chuàng)建時(shí)必須設(shè)置可用令牌的初始數(shù)量permits,用于控制并發(fā)時(shí)同時(shí)獲取資源權(quán)限的線程數(shù)量,這篇文章主要介紹了Java中的Semaphore如何使用,需要的朋友可以參考下
    2022-06-06
  • java實(shí)現(xiàn)分布式鎖的常用三種方式

    java實(shí)現(xiàn)分布式鎖的常用三種方式

    本文主要介紹了java實(shí)現(xiàn)分布式鎖,一般有這3種方式,基于數(shù)據(jù)庫(kù)實(shí)現(xiàn)的分布式鎖、基于Redis實(shí)現(xiàn)的分布式鎖和基于Zookeeper實(shí)現(xiàn)的分布式鎖,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-08-08
  • Java中GC的工作原理詳細(xì)介紹

    Java中GC的工作原理詳細(xì)介紹

    這篇文章主要介紹了Java中GC的工作原理詳細(xì)介紹的相關(guān)資料,需要的朋友可以參考下
    2017-03-03

最新評(píng)論

偏关县| 隆回县| 新平| 山西省| 曲沃县| 嫩江县| 六枝特区| 潍坊市| 东方市| 南木林县| 建德市| 罗江县| 望谟县| 淳化县| 焦作市| 隆安县| 报价| 谷城县| 昌江| 彰武县| 昔阳县| 张家川| 高淳县| 桐乡市| 桓台县| 普宁市| 内丘县| 马龙县| 济源市| 平和县| 芦溪县| 固镇县| 泰来县| 屏边| 吉隆县| 迭部县| 枣阳市| 隆化县| 卓尼县| 大石桥市| 塘沽区|