jdk1.8之后,JVM內(nèi)存結(jié)構(gòu)如下
所謂的StringTable,即字符串常量池(以下簡(jiǎn)稱(chēng)串池),存放在堆內(nèi)存中。
我們先介紹一下intern方法
String s = "ab";
//將這個(gè)字符串對(duì)象嘗試放入串池,如果有則并不會(huì)放入,如果沒(méi)有則放入串池,會(huì)把串池中的對(duì)象返回
String s2 = s.intern();
調(diào)優(yōu)方法1.因?yàn)镾tringTable是由HashTable實(shí)現(xiàn)的,所以可以適當(dāng)增加HashTable桶的個(gè)數(shù),來(lái)減少字符串放入串池所需要的時(shí)間。
示例代碼:遍歷文本文件,讀取每一行的內(nèi)容放入串池
public class Demo1_24 {
public static void main(String[] args) throws IOException {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("linux.words"), "utf-8"))) {
String line = null;
long start = System.nanoTime();
while (true) {
line = reader.readLine();
if (line == null) {
break;
}
line.intern();
}
System.out.println("cost:" + (System.nanoTime() - start) / 1000000);
}
}
}
linux.words是存放文本的文件(實(shí)際文本有四百多萬(wàn)行,只粘貼部分做示例)
1080
10-point
10th
11-point
12-point
16-point
18-point
1st
2
20-point
2,4,5-t
2,4-d
2D
2nd
30-30
3-D
3-d
3D
3M
3rd
48-point
4-D
4GL
4H
4th
5-point
5-T
5th
6-point
6th
7-point
7th
8-point
8th
9-point
9th
-a
A
A.
a
a'
a-
a.
A-1
A1
a1
A4
A5
AA
aa
我們運(yùn)行程序,發(fā)現(xiàn)耗時(shí)不到1s
然后我們?cè)O(shè)置JVM運(yùn)行參數(shù),修改桶的數(shù)量為1009,再次運(yùn)行
-XX:+PrintStringTableStatistics -XX:StringTableSize=1009
運(yùn)行結(jié)果耗時(shí)8秒 如下圖
StringTable默認(rèn)的桶的數(shù)量是60013,當(dāng)桶的數(shù)量設(shè)置變小,哈希碰撞的概率增加,鏈表長(zhǎng)度
變長(zhǎng),數(shù)據(jù)插入就會(huì)變慢,可以適當(dāng)增加HashTable桶的個(gè)數(shù),來(lái)減少字符串放入串池所需要的時(shí)間。
調(diào)優(yōu)方法2:如果應(yīng)用里有大量的字符串,而且字符串可能存在重復(fù)的問(wèn)題,可以通過(guò)intern方法讓字符串入池,減少字符串個(gè)數(shù)(觸發(fā)垃圾回收 沒(méi)入池的字符串被回收掉),節(jié)約堆內(nèi)存的使用
示例代碼:同樣是遍歷上述的文本文件,將每一行的內(nèi)容放入ArrayList中,循環(huán)操作10次
public class Demo1_25 {
public static void main(String[] args) throws IOException {
Listaddress = new ArrayList<>();
System.in.read();
for (int i = 0; i< 10; i++) {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("linux.words"), "utf-8"))) {
String line = null;
long start = System.nanoTime();
while (true) {
line = reader.readLine();
if(line == null) {
break;
}
address.add(line);
}
System.out.println("cost:" +(System.nanoTime()-start)/1000000);
}
}
System.in.read();
}
}
運(yùn)行以上代碼,我們控制臺(tái)輸入
jvisualvm?
查看字符串所占用的內(nèi)存使用情況?
然后我們敲下Enter執(zhí)行我們的主程序,遍歷文本文件,發(fā)現(xiàn)內(nèi)存占用飆高很多
然后我們修改代碼(只改了一行代碼,address.add(line.intern())
public class Demo1_25 {
public static void main(String[] args) throws IOException {
Listaddress = new ArrayList<>();
System.in.read();
for (int i = 0; i< 10; i++) {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("linux.words"), "utf-8"))) {
String line = null;
long start = System.nanoTime();
while (true) {
line = reader.readLine();
if(line == null) {
break;
}
//僅修改這一處代碼
address.add(line.intern());
}
System.out.println("cost:" +(System.nanoTime()-start)/1000000);
}
}
System.in.read();
}
}
再運(yùn)行查看內(nèi)存占用情況,下降了很多
我們循環(huán)遍歷10次,會(huì)在堆中產(chǎn)生很多重復(fù)的字符串,而ArrayList中存放的對(duì)象都來(lái)自串池,堆中的字符串 如果沒(méi)被引用,會(huì)被垃圾回收掉,從而節(jié)約了堆內(nèi)存的使用
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級(jí)流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級(jí)服務(wù)器適合批量采購(gòu),新人活動(dòng)首月15元起,快前往官網(wǎng)查看詳情吧
文章名稱(chēng):JVM調(diào)優(yōu)之StringTable調(diào)優(yōu)-創(chuàng)新互聯(lián)
文章來(lái)源:http://jinyejixie.com/article20/dpdejo.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供建站公司、網(wǎng)站收錄、軟件開(kāi)發(fā)、標(biāo)簽優(yōu)化、微信小程序、網(wǎng)站策劃
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容