JVM各内存区域存放内容
一、方法區(qū)存放內(nèi)容:
1.類的全限定名(類的全路徑名)。
2.類的直接超類的權(quán)全限定名(如果這個(gè)類是Object,則它沒有超類)。
3.類的類型(類或接口)。
4.類的訪問修飾符,public,abstract,final等。
5.類的直接接口全限定名的有序列表。
6.常量池(字段,方法信息,靜態(tài)變量,類型引用(class))等
當(dāng)jvm使用類裝載器裝在某個(gè)類時(shí),它首先要定位到對(duì)應(yīng)的class文件,然后讀入這個(gè)class文件,最后提取該文件的內(nèi)容信息,并將這些信息存儲(chǔ)到方法區(qū),最后返回一個(gè)class實(shí)例。
方法區(qū)是系統(tǒng)分配的一個(gè)內(nèi)存邏輯區(qū)域,是一塊所有線程共享的內(nèi)存區(qū)域,用來存儲(chǔ)類型信息(類型信息可以理解為類的描述信息(類的全限定名,訪問修飾符,字段,方法等)),方法區(qū)的大小決定了系統(tǒng)可以包含多少個(gè)類,如果系統(tǒng)類太多,方法區(qū)內(nèi)存不夠會(huì)導(dǎo)致方法區(qū)溢出,虛擬機(jī)同樣會(huì)拋出內(nèi)存溢出信息。方法去特點(diǎn):
1.方法區(qū)是線程安全的,由于所有的線程都共享方法區(qū),所以方法區(qū)里的數(shù)據(jù)訪問必須被設(shè)計(jì)成線程安全的。例如,假如同時(shí)有兩個(gè)線程都企圖訪問方法區(qū)中的同一個(gè)類,而這個(gè)類還沒有被裝入jvm,那么只允許一個(gè)線程去裝在它,而其他線程必須等待。
2.方法去的大小不必是固定的,jvm可根據(jù)應(yīng)用需要?jiǎng)討B(tài)調(diào)整,同時(shí),方法區(qū)也不一定是連續(xù)的,方法區(qū)可以在一個(gè)堆(甚至是jvm自己的堆)中自由分配。
3.方法區(qū)也可被垃圾收集,當(dāng)某個(gè)類不在被使用時(shí),jvm將卸載這個(gè)類,進(jìn)行垃圾收集。
?
String str=new String("hello");
堆 存放的是new出來的對(duì)象? jvm中只有一個(gè)堆區(qū) 被所有的線程共享
棧 是變量str? 每個(gè)棧中的數(shù)據(jù)私有的 其他棧不能訪問。
方法區(qū) 是“hello”;被所有的線程共享,方法區(qū)包含所有的class static變量。
?
程序計(jì)數(shù)器:
一、先來看看概念
多線程的Java應(yīng)用程序:為了讓每個(gè)線程正常工作就提出了程序計(jì)數(shù)器(Programe Counter Register),每個(gè)線程都有自己的程序計(jì)數(shù)器這樣當(dāng)線程執(zhí)行切換的時(shí)候就可以在上次執(zhí)行的基礎(chǔ)上繼續(xù)執(zhí)行,僅僅從一條線程線性執(zhí)行的角度而言,代碼是一條一條的往下執(zhí)行的,這個(gè)時(shí)候就是程序計(jì)數(shù)器;JVM就是通過讀取程序計(jì)數(shù)器的值來決定下一條需要執(zhí)行的字節(jié)碼指令,進(jìn)而進(jìn)行選擇語句、循環(huán)、異常處理等;
這個(gè)還沒看懂的話不要緊,繼續(xù)往下走咯。
二、簡(jiǎn)單粗暴的舉例
1.生活中的案例
比如老王正在看電影,他看到三十五分鐘的時(shí)候,突然他的QQ好友給他開視頻聊天,這時(shí)候肯定打斷他看電影了,假設(shè)他qq好友和他視頻完了,他肯定要接著他那35分鐘的進(jìn)度去繼續(xù)看,這時(shí)候他怎么知道我看到35分鐘了?這時(shí)候程序計(jì)數(shù)器就起了作用,他負(fù)責(zé)管理進(jìn)度。
是不是略微懂了一點(diǎn)呢?
2.代碼層面的案例
將上面的例子轉(zhuǎn)換成代碼,是這樣的:
A線程正在執(zhí)行HelloWorld.class的第三十五行。這時(shí)候CPU時(shí)間片被B線程搶走了,當(dāng)A線程重新被分配到時(shí)間片時(shí),他怎么知道我的class運(yùn)行到哪了?這時(shí)候他可以看程序計(jì)數(shù)器在哪個(gè)位置。
這下總該明白了吧?
三、JVM程序計(jì)數(shù)器的總結(jié)
程序計(jì)數(shù)器作用不多說了,我個(gè)人感覺他是為了多線程而生的,單線程情況下完全不需要他。從案例中不難發(fā)現(xiàn),程序計(jì)數(shù)器是每個(gè)線程獨(dú)有的,并非線程共享的,所以是線程安全的!
?
本地方法棧:
對(duì)于一個(gè)運(yùn)行中的Java程序而言,它還可能會(huì)用到一些跟本地方法相關(guān)的數(shù)據(jù)區(qū)。當(dāng)某個(gè)線程調(diào)用一個(gè)本地方法時(shí),它就進(jìn)入了一個(gè)全新的并且不再受虛擬機(jī)限制的世界。本地方法可以通過本地方法接口來訪問虛擬機(jī)的運(yùn)行時(shí)數(shù)據(jù)區(qū),但不止如此,它還可以做任何它想做的事情。
本地方法本質(zhì)上時(shí)依賴于實(shí)現(xiàn)的,虛擬機(jī)實(shí)現(xiàn)的設(shè)計(jì)者們可以自由地決定使用怎樣的機(jī)制來讓Java程序調(diào)用本地方法。
任何本地方法接口都會(huì)使用某種本地方法棧。當(dāng)線程調(diào)用Java方法時(shí),虛擬機(jī)會(huì)創(chuàng)建一個(gè)新的棧幀并壓入Java棧。然而當(dāng)它調(diào)用的是本地方法時(shí),虛擬機(jī)會(huì)保持Java棧不變,不再在線程的Java棧中壓入新的幀,虛擬機(jī)只是簡(jiǎn)單地動(dòng)態(tài)連接并直接調(diào)用指定的本地方法。
如果某個(gè)虛擬機(jī)實(shí)現(xiàn)的本地方法接口是使用C連接模型的話,那么它的本地方法棧就是C棧。當(dāng)C程序調(diào)用一個(gè)C函數(shù)時(shí),其棧操作都是確定的。傳遞給該函數(shù)的參數(shù)以某個(gè)確定的順序壓入棧,它的返回值也以確定的方式傳回調(diào)用者。同樣,這就是虛擬機(jī)實(shí)現(xiàn)中本地方法棧的行為。
很可能本地方法接口需要回調(diào)Java虛擬機(jī)中的Java方法,在這種情況下,該線程會(huì)保存本地方法棧的狀態(tài)并進(jìn)入到另一個(gè)Java棧。
下圖描繪了這樣一個(gè)情景,就是當(dāng)一個(gè)線程調(diào)用一個(gè)本地方法時(shí),本地方法又回調(diào)虛擬機(jī)中的另一個(gè)Java方法。
這幅圖展示了JAVA虛擬機(jī)內(nèi)部線程運(yùn)行的全景圖。一個(gè)線程可能在整個(gè)生命周期中都執(zhí)行Java方法,操作它的Java棧;或者它可能毫無障礙地在Java棧和本地方法棧之間跳轉(zhuǎn)。
該線程首先調(diào)用了兩個(gè)Java方法,而第二個(gè)Java方法又調(diào)用了一個(gè)本地方法,這樣導(dǎo)致虛擬機(jī)使用了一個(gè)本地方法棧。假設(shè)這是一個(gè)C語言棧,其間有兩個(gè)C函數(shù),第一個(gè)C函數(shù)被第二個(gè)Java方法當(dāng)做本地方法調(diào)用,而這個(gè)C函數(shù)又調(diào)用了第二個(gè)C函數(shù)。之后第二個(gè)C函數(shù)又通過本地方法接口回調(diào)了一個(gè)Java方法(第三個(gè)Java方法),最終這個(gè)Java方法又調(diào)用了一個(gè)Java方法(它成為圖中的當(dāng)前方法)。
?
?
總結(jié)
以上是生活随笔為你收集整理的JVM各内存区域存放内容的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: iOS UITableview 禁止上下
- 下一篇: 比尔盖茨的风流情史,妻子同意他与前女友同