常量池
1.使用String并不一定創(chuàng)建對象
String s1 = "abc"; // 常量池中沒有,則創(chuàng)建"abc"對像,1.6會生成新的對像放入常量池根欧,1.7之后是放入的引用
String s2 = "abc";
System.out.println(s1 == s2); // true
System.out.println(s1.equals(s2)); // true
2.使用new String一定創(chuàng)建新對象
3.String類型的內(nèi)存模型
Java8以及以后的字符串新建時责球,直接在堆中生成對象,而字符創(chuàng)常量池位于Metaspace岛琼。必要的時候,會把堆中的指針存入Metaspace, 而不是復(fù)制巢株。
Java7的字符串新建時槐瑞,直接在堆中生成對象,而字符創(chuàng)常量池位于方法區(qū)的常量池阁苞。必要的時候困檩,復(fù)制一份存入常量池
Metaspace位于虛擬機(jī)以外的直接內(nèi)存,因此大小和外部直接內(nèi)存有關(guān)那槽,但也可以通過指定參數(shù)設(shè)置-XX:MetaspaceSize=8m -XX:MaxMetaspaceSize=8m
4.String.intern方法
即常量池存在悼沿,返回常量池中的那個對象,常量池不存在骚灸,則放入常量池糟趾,并返回本身。由此推斷兩個公式:
str.intern() == str //證明返回this本身甚牲,證明常量池不存在义郑。
str.intern() != str //證明返回常量池中已存在的對象,不等于新建的對象丈钙。
5.Java運(yùn)行時數(shù)據(jù)區(qū)域
jvm內(nèi)存區(qū)域
Java 內(nèi)存區(qū)域
在 1.8 之前是:
- 線程私有的:程序計數(shù)器魔慷、虛擬機(jī)棧、本地方法棧
- 線程共享的:堆著恩、方法區(qū)
- 直接內(nèi)存
從 1.8 開始:
- 線程私有的:程序計數(shù)器院尔、虛擬機(jī)棧蜻展、本地方法棧
- 線程共享的:堆
- 直接內(nèi)存以及里面的 元空間
程序計數(shù)器:指向下一條需要執(zhí)行的字節(jié)碼;記錄當(dāng)前線程的位置便于線程切換與恢復(fù)邀摆;
唯一 一個不會出現(xiàn) OOM 的區(qū)域
虛擬機(jī)棧:描述了Java方法執(zhí)行的內(nèi)存模型纵顾,創(chuàng)建棧幀,保存該本地方法的局部變量表栋盹、操作數(shù)棧施逾、動態(tài)鏈接、出口信息例获。
本地方法棧:描述 native 的方法執(zhí)行汉额,會創(chuàng)建棧幀。也保存了該本地方法的局部變量表榨汤、操作數(shù)棧蠕搜、動態(tài)鏈接、出口信息收壕。
堆:主要用于存放對象