摘要:一內(nèi)存區(qū)域虛擬機在運行時,會把內(nèi)存空間分為若干個區(qū)域,根據(jù)虛擬機規(guī)范版的規(guī)定,虛擬機所管理的內(nèi)存區(qū)域分為如下部分方法區(qū)堆內(nèi)存虛擬機棧本地方法棧程序計數(shù)器。
前言在JVM的管控下,Java程序員不再需要管理內(nèi)存的分配與釋放,這和在C和C++的世界是完全不一樣的。所以,在JVM的幫助下,Java程序員很少會關(guān)注內(nèi)存泄露和內(nèi)存溢出的問題。但是,一旦JVM發(fā)生這些情況的時候,如果你不清楚JVM內(nèi)存的內(nèi)存管理機制是很難定位與解決問題的。
一、JVM 內(nèi)存區(qū)域Java虛擬機在運行時,會把內(nèi)存空間分為若干個區(qū)域,根據(jù)《Java虛擬機規(guī)范(Java SE 7 版)》的規(guī)定,Java虛擬機所管理的內(nèi)存區(qū)域分為如下部分:方法區(qū)、堆內(nèi)存、虛擬機棧、本地方法棧、程序計數(shù)器。
1、方法區(qū)
方法區(qū)主要用于存儲虛擬機加載的類信息、常量、靜態(tài)變量,以及編譯器編譯后的代碼等數(shù)據(jù)。在jdk1.7及其之前,方法區(qū)是堆的一個“邏輯部分”(一片連續(xù)的堆空間),但為了與堆做區(qū)分,方法區(qū)還有個名字叫“非堆”,也有人用“永久代”(HotSpot對方法區(qū)的實現(xiàn)方法)來表示方法區(qū)。
從jdk1.7已經(jīng)開始準備“去永久代”的規(guī)劃,jdk1.7的HotSpot中,已經(jīng)把原本放在方法區(qū)中的靜態(tài)變量、字符串常量池等移到堆內(nèi)存中,(常量池除字符串常量池還有class常量池等),這里只是把字符串常量池移到堆內(nèi)存中;在jdk1.8中,方法區(qū)已經(jīng)不存在,原方法區(qū)中存儲的類信息、編譯后的代碼數(shù)據(jù)等已經(jīng)移動到了元空間(MetaSpace)中,元空間并沒有處于堆內(nèi)存上,而是直接占用的本地內(nèi)存(NativeMemory)。根據(jù)網(wǎng)上的資料結(jié)合自己的理解對jdk1.3~1.6、jdk1.7、jdk1.8中方法區(qū)的變遷畫了張圖如下(如有不合理的地方希望讀者指出):
去永久代的原因有:
字符串存在永久代中,容易出現(xiàn)性能問題和內(nèi)存溢出。
類及方法的信息等比較難確定其大小,因此對于永久代的大小指定比較困難,太小容易出現(xiàn)永久代溢出,太大則容易導(dǎo)致老年代溢出。
永久代會為 GC 帶來不必要的復(fù)雜度,并且回收效率偏低。
堆內(nèi)存主要用于存放對象和數(shù)組,它是JVM管理的內(nèi)存中最大的一塊區(qū)域,堆內(nèi)存和方法區(qū)都被所有線程共享,在虛擬機啟動時創(chuàng)建。在垃圾收集的層面上來看,由于現(xiàn)在收集器基本上都采用分代收集算法,因此堆還可以分為新生代(YoungGeneration)和老年代(OldGeneration),新生代還可以分為 Eden、From Survivor、To Survivor。
3、程序計數(shù)器程序計數(shù)器是一塊非常小的內(nèi)存空間,可以看做是當(dāng)前線程執(zhí)行字節(jié)碼的行號指示器,每個線程都有一個獨立的程序計數(shù)器,因此程序計數(shù)器是線程私有的一塊空間,此外,程序計數(shù)器是Java虛擬機規(guī)定的唯一不會發(fā)生內(nèi)存溢出的區(qū)域。
4、虛擬機棧虛擬機棧也是每個線程私有的一塊內(nèi)存空間,它描述的是方法的內(nèi)存模型,直接看下圖所示:
虛擬機會為每個線程分配一個虛擬機棧,每個虛擬機棧中都有若干個棧幀,每個棧幀中存儲了局部變量表、操作數(shù)棧、動態(tài)鏈接、返回地址等。一個棧幀就對應(yīng) Java 代碼中的一個方法,當(dāng)線程執(zhí)行到一個方法時,就代表這個方法對應(yīng)的棧幀已經(jīng)進入虛擬機棧并且處于棧頂?shù)奈恢?,每一個 Java 方法從被調(diào)用到執(zhí)行結(jié)束,就對應(yīng)了一個棧幀從入棧到出棧的過程。
5、本地方法棧本地方法棧與虛擬機棧的區(qū)別是,虛擬機棧執(zhí)行的是 Java 方法,本地方法棧執(zhí)行的是本地方法(Native Method),其他基本上一致,在 HotSpot 中直接把本地方法棧和虛擬機棧合二為一,這里暫時不做過多敘述。
6、元空間上面說到,jdk1.8 中,已經(jīng)不存在永久代(方法區(qū)),替代它的一塊空間叫做 “ 元空間 ”,和永久代類似,都是 JVM 規(guī)范對方法區(qū)的實現(xiàn),但是元空間并不在虛擬機中,而是使用本地內(nèi)存,元空間的大小僅受本地內(nèi)存限制,但可以通過 -XX:MetaspaceSize 和 -XX:MaxMetaspaceSize 來指定元空間的大小。
總結(jié)JVM內(nèi)存區(qū)域劃分,便于它能夠更加高效的管理自身的內(nèi)存。當(dāng)程序中出現(xiàn)這種由于JVM造成的內(nèi)存溢出的情況的時候,需要根據(jù)不同的情況做不同的分析與處理。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/7199.html
摘要:從使用到原理學(xué)習(xí)線程池關(guān)于線程池的使用,及原理分析分析角度新穎面向切面編程的基本用法基于注解的實現(xiàn)在軟件開發(fā)中,分散于應(yīng)用中多出的功能被稱為橫切關(guān)注點如事務(wù)安全緩存等。 Java 程序媛手把手教你設(shè)計模式中的撩妹神技 -- 上篇 遇一人白首,擇一城終老,是多么美好的人生境界,她和他歷經(jīng)風(fēng)雨慢慢變老,回首走過的點點滴滴,依然清楚的記得當(dāng)初愛情萌芽的模樣…… Java 進階面試問題列表 -...
摘要:請注意,我們在聊聊單元測試遇到問題多思考多查閱多驗證,方能有所得,再勤快點樂于分享,才能寫出好文章。單元測試是指對軟件中的最小可測試單元進行檢查和驗證。 JAVA容器-自問自答學(xué)HashMap 這次我和大家一起學(xué)習(xí)HashMap,HashMap我們在工作中經(jīng)常會使用,而且面試中也很頻繁會問到,因為它里面蘊含著很多知識點,可以很好的考察個人基礎(chǔ)。但一個這么重要的東西,我為什么沒有在一開始...
摘要:運行時數(shù)據(jù)區(qū)域的學(xué)習(xí),是學(xué)習(xí)以及機制的基礎(chǔ),也是深入理解對象創(chuàng)建及運行過程的前提。了解內(nèi)存區(qū)域劃分,是學(xué)習(xí)概念的前提。 Java 運行時數(shù)據(jù)區(qū)域的學(xué)習(xí),是學(xué)習(xí) jvm 以及 GC 機制的基礎(chǔ),也是深入理解 java 對象創(chuàng)建及運行過程的前提。廢話不多說,直接進入正題: 一張圖總結(jié) showImg(https://segmentfault.com/img/bVOMAn?w=685&h=5...
摘要:我的是忙碌的一年,從年初備戰(zhàn)實習(xí)春招,年三十都在死磕源碼,三月份經(jīng)歷了阿里五次面試,四月順利收到實習(xí)。因為我心理很清楚,我的目標是阿里。所以在收到阿里之后的那晚,我重新規(guī)劃了接下來的學(xué)習(xí)計劃,將我的短期目標更新成拿下阿里轉(zhuǎn)正。 我的2017是忙碌的一年,從年初備戰(zhàn)實習(xí)春招,年三十都在死磕JDK源碼,三月份經(jīng)歷了阿里五次面試,四月順利收到實習(xí)offer。然后五月懷著忐忑的心情開始了螞蟻金...
閱讀 1533·2021-11-23 09:51
閱讀 3646·2021-09-26 09:46
閱讀 2135·2021-09-22 10:02
閱讀 1849·2019-08-30 15:56
閱讀 3333·2019-08-30 12:51
閱讀 2235·2019-08-30 11:12
閱讀 2069·2019-08-29 13:23
閱讀 2331·2019-08-29 13:16