中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

什么是JVM元數據區

發布時間:2021-07-19 09:43:43 來源:億速云 閱讀:286 作者:chen 欄目:大數據

這篇文章主要講解了“什么是JVM元數據區”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“什么是JVM元數據區”吧!


 
元數據區

元數據區的概念出現在Java8以后,在Java8以前成為方法區,元數據區也是一塊線程共享的內存區域,主要用來保存被虛擬機加載的類信息、常量、靜態變量以及即時編譯器編譯后的代碼等數據。

由于元數據存儲的信息不容易變動,因此它被安置在一塊堆外內存,大小由-XX:MaxMetaspaceSize指定。

public class MetaSpaceTest {
   public static void main(String[] args) {        int i = 0;        try {            for (i = 0; i < 100000; i++) {                new CglibBean(new HashMap<>());            }        } catch (Exception e) {            System.out.println(e.getMessage());        } finally {            System.out.println("total create count:" + i);        }    }
   public static class CglibBean {
       public CglibBean(Object object) {            Enhancer enhancer = new Enhancer();            enhancer.setUseCache(false);            enhancer.setCallback((MethodInterceptor) (obj, method, args, proxy) -> obj);            enhancer.setSuperclass(object.getClass());            enhancer.create();        }    }}
 

上述代碼通過Cglib生成大量的HashMap代理,下面我們在運行這段代碼的時候指定下列參數

-XX:MaxMetaspaceSize=100M -XX:+PrintGCDetails
 
什么是JVM元數據區  


當我們程序循環至3660次,也就是說我們大約在生成了約3660個代理類以后元數據區發生了內存溢出,下面將MaxMetaspaceSize改為50M執行,

什么是JVM元數據區  


從上圖可以看出當我們生成了1710個代理類以后元數據區發生了內存溢出,可見一個元數據區的大小決定了Java虛擬機可以裝載的類的多少。

 
運行時常量池

在元數據區中還有一塊區域稱為運行時常量池,此區域用來程序運行期間產生的常量,以及編譯期生成的各種字面量和符號引用經類加載后的內容。

在Java中大概存儲三種常量池概念,下面我們來講一下Java中其他兩種常量池,幫助讀者了解他們中的區別。

首先大家在理解常量池的時候不要簡單的理解為被final修飾的變量,常量在這里的含義是一切不變的東西,包括final修飾的變量、字面量、類和接口全限定名、字段、方法名稱以及修飾符等永恒不變的東西

 類文件常量池

類文件常量池是指.class文件中的Constant_Pool項,如下圖,類文件常量池存放的都是一些字面量和符號引用。什么是JVM元數據區

并不是所有的字面量都會存儲在類文件常量池中,比如對于方法內(注意是方法)整數字面量,如果值在-32768~32767之間則會被直接嵌入JVM指令中去,不會保存在常量池中。所以讀者不會在常量池中知道CONSTANT_Integer_info為1的符號引用。

類文件常量池產生于編譯時期,當JVM加載類文件時會將類文件常量池中的符合引用替換直接引用,加載之后的類文件信息將會被存放在運行時常量池。

 字符串池

字符串池存在JDK1.6以前是存放在永久區中,但是在JDK1.7以后就被轉移到堆上。

public static void intern() {    String s1 = new String("he") + new String("llo");    String s2 = s1.intern();    System.out.println(s1 == s2);}
 

上述代碼在JDK1.6的時候將會創建6個對象,首先new String("he")會在堆上創一個對象,并且"he"字面量會在永久區的字符串池上創建一個對象,new String("llo")同理創建了兩個對象,最后的+又創建了一個對象,當調用intern()方法時,首先會去查找字符串池查找是否有hello內容的對象,發現沒有則會在永久區中再創建一個對象,因此總共有6個對象,由于s1是堆中的對象,s2是永久區字符串池中的對象,因此s1==s2結果為false,詳情如下圖

什么是JVM元數據區  


但是在JDK1.6以后效果不再如此,原因就是由于字符串常量池被移到了堆中,intern方法也做了優化,在JDK1.6以后上述代碼將會創建5個對象,首先new String("he")會在堆上創一個對象,并且"he"字面量也會在堆上創建一個對象, new String("llo")同理創建了兩個對象,最后的+又創建了一個對象。當intern調用時,首先會在字符串池中查找是否有hello內容的對象,發現沒有,此時不會主動創建而是先去查找堆中是否有hello內容的對象,如果有則直接將指針指向堆中的示例,因此這里一共會創建5個對象,由于s1和s2指向的是同一個對象實例,因此s1==s2為true,詳情如下圖

什么是JVM元數據區  
 

問題

為了幫助各位讀者真正理解字符串常量池,下面有兩段代碼,請在腦海中給出結果,然后再進行Coding驗證

public static void intern() {    String s1 = new String("he") + new String("llo");    String s2 = s1.intern();    String s3 = "hello";    System.out.println(s1 == s3);    System.out.println(s1 == s2);}
 
public static void intern() {    String s3 = "hello";    String s1 = new String("he") + new String("llo");    String s2 = s1.intern();    System.out.println(s1 == s3);    System.out.println(s1 == s2);}

感謝各位的閱讀,以上就是“什么是JVM元數據區”的內容了,經過本文的學習后,相信大家對什么是JVM元數據區這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

jvm
AI

静宁县| 迁安市| 双江| 南安市| 习水县| 时尚| 方山县| 罗山县| 黔江区| 林周县| 武城县| 双鸭山市| 东乌珠穆沁旗| 株洲市| 龙江县| 安国市| 武邑县| 大足县| 平泉县| 昆明市| 翁牛特旗| 琼中| 肇州县| 南郑县| 临汾市| 龙州县| 根河市| 望城县| 若尔盖县| 嫩江县| 临武县| 富民县| 涞源县| 东海县| 赣州市| 孝感市| 南安市| 木兰县| 扶余县| 滨州市| 杭锦旗|