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