亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

通過(guò)String.intern()方法淺談堆中常量池

 更新時(shí)間:2019年06月14日 14:46:40   作者:宸小朔  
這篇文章主要介紹了通過(guò)String.intern()方法淺談堆中常量池,在JDK7之前,字符串常量是存在永久帶Perm 區(qū)的,JDK7開(kāi)始在將常量池遷移到堆中,這個(gè)變化也導(dǎo)致了String的新特性,下面我們慢慢進(jìn)行介紹。,需要的朋友可以參考下

簡(jiǎn)介

String是我們最常用的一個(gè)類,和普通java類一樣其對(duì)象會(huì)存在java堆中。但是String類有其特殊之處,可以通過(guò)new方法生成,也可以通過(guò)帶引號(hào)的字符串常量直接賦值。在JDK7之前,字符串常量是存在永久帶Perm 區(qū)的,JDK7開(kāi)始在將常量池遷移到堆中,這個(gè)變化也導(dǎo)致了String的新特性,下面我們慢慢進(jìn)行介紹。

String.intern()方法

簡(jiǎn)單的說(shuō),String.intern()方法的作用就是返回常量池中字符串對(duì)象,在對(duì)該方法進(jìn)行詳解之前,我們看幾個(gè)創(chuàng)建字符串對(duì)象的例子。以下說(shuō)明及運(yùn)行結(jié)果都是以JDK8為java環(huán)境。

(1)直接賦值字符串常量

​ 這種方式會(huì)判斷常量池中是否存在字符串常量,如果存在返回該常量對(duì)象,否則在常量池中創(chuàng)建常量對(duì)象并返回。

//在常量池中創(chuàng)建常量“abc”,s1,s2指向常量池中對(duì)象地址 
String s1 = "abc";
String s2 = "abc";
System.out.println(s1 == s2);//true

(2)通過(guò)new關(guān)鍵字創(chuàng)建

​ 這種方式會(huì)在堆上創(chuàng)建String對(duì)象,如果常量池中沒(méi)有該常量,將常量加入常量池中。

//在堆上創(chuàng)建對(duì)象S3,S4,常量池中創(chuàng)建對(duì)象“abc”
String s3 = new String("abc");
String s4 = new String("abc");
System.out.println(s3 == s4);//false

(3)字符串常量相加

這種方式如s5,會(huì)在常量池中創(chuàng)建"cd","ef","cdef"三個(gè)對(duì)象,s5指向常量池中的"cdef"對(duì)象。

String s5 = "cd" + "ef";
String s6 = "cdef";
System.out.println(s5==s6);//true

(4)兩個(gè)new的String對(duì)象相加

這種方式如s7,會(huì)在堆中創(chuàng)建三個(gè)對(duì)象"gh"對(duì)象,"lm"對(duì)象,以及"ghlm"對(duì)象,在常量池中創(chuàng)建對(duì)象"gh","lm"。

String s7 = new String("gh") + new String("lm");
String s8 = "ghlm";
System.out.println(s7==s8);//false

(5)字符串常量與new的String對(duì)象相加

這種方式如s9,會(huì)在堆中創(chuàng)建兩個(gè)對(duì)象“op”,“mnop”,并將字符串常量“op”, "mn"加到常量池中。

String s9 = "mn" + new String("op");
String s10 = "mnop";
System.out.println(s9==s10);//false

了解字符串常量的創(chuàng)建及其在內(nèi)存中的存儲(chǔ),我們看native方法intern()的作用:判斷String對(duì)象的常量值是否存在于常量池中,如果存在并且是常量池對(duì)象,返回該常量池對(duì)象;如果存在并且是指向堆中的對(duì)象,返回堆中對(duì)象地址;如果不存在,則將對(duì)象的引用復(fù)制到常量池,并返回該對(duì)象的引用。下面我們看幾條語(yǔ)句的運(yùn)行結(jié)果,第一個(gè)輸出之所以為true,

String s11 = new String("a") + new String("a");
s11.intern();//由于常量池中無(wú)“aa”,因此在常量池中建“aa”的引用,指向堆中的s11
String s12 = "aa";//s12指向常量池中的對(duì)象(該對(duì)象指向S11)
System.out.println(s11 == s12.intern());//true
String s13 = new String("b");
s13.intern();//常量池中已經(jīng)有“b”了,不做任何操作
String s14 = "b";
System.out.println(s13==s14.intern());//false

如果理解了以上運(yùn)行的結(jié)果,對(duì)intern()方法的左右就掌握的差不多了。那么久可以開(kāi)始我們的主題,string pool,字符串常量池。

字符串常量池

字符串常量池是jvm為了減小內(nèi)存開(kāi)銷而在創(chuàng)建字符串對(duì)象時(shí)的一個(gè)優(yōu)化,類似緩沖區(qū)。在hotspot中,字符串常量池是一個(gè)叫做StringTable的HashTable,默認(rèn)長(zhǎng)度是1009,在JDK7開(kāi)始可以通過(guò)"-XX:StringTableSize=1009" 參數(shù)來(lái)設(shè)置,字符串常量池?cái)?shù)據(jù)可以被gc回收(在JDK6及其以前,字符串常量存在永久帶無(wú)法被gc回收,如果添加太多字符串常量到該區(qū)域,容易發(fā)生OOM)。由于字符串常量池是利用HashTable實(shí)現(xiàn),因此一定會(huì)發(fā)生hash碰撞。

jvm在這方面做了一定優(yōu)化,會(huì)根據(jù)hashTable的碰撞情況來(lái)決定是否做rehash,當(dāng)從這個(gè)StringTable里查找某個(gè)字符串是否存在,如果對(duì)其對(duì)應(yīng)的桶鏈表進(jìn)行遍歷,遍歷超過(guò)了100個(gè)節(jié)點(diǎn)還是沒(méi)有找到,那就會(huì)設(shè)置一個(gè)flag,讓下次進(jìn)入到safepoint的時(shí)候做一次rehash動(dòng)作,盡量減少碰撞的發(fā)生。當(dāng)然,在數(shù)據(jù)量比較大的情況下,這也無(wú)法從根本上解決問(wèn)題,只能設(shè)置StringTableSize的值來(lái)緩解。

由于JDK7開(kāi)始字符串常量池在堆中分布,所以young gc過(guò)程會(huì)掃描該區(qū)域,以保證處于新生代的String對(duì)象不會(huì)被回收掉,因此如果字符串常量區(qū)非常龐大會(huì)導(dǎo)致young gc過(guò)程掃描的時(shí)間也會(huì)變長(zhǎng)。但是,young gc階段并不會(huì)對(duì)字符串常量區(qū)進(jìn)行回收,具體回收階段是在Full gc或者CMS gc階段(題外話:我覺(jué)得full gc這個(gè)名字并不是很好,容易理解為對(duì)所有區(qū)域進(jìn)行回收,其實(shí)full GC是對(duì)老年代的STW的gc,full gc的次數(shù)是老年代gc的STW次數(shù),時(shí)間是老年代STW的總時(shí)間)。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Springboot 2.6集成redis maven報(bào)錯(cuò)的坑記錄

    Springboot 2.6集成redis maven報(bào)錯(cuò)的坑記錄

    這篇文章主要介紹了Springboot 2.6集成redis maven報(bào)錯(cuò)的坑記錄,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • 常用的Spring Boot調(diào)用外部接口方式實(shí)現(xiàn)數(shù)據(jù)交互

    常用的Spring Boot調(diào)用外部接口方式實(shí)現(xiàn)數(shù)據(jù)交互

    Spring Boot提供了多種調(diào)用外部接口的方式,可以方便地實(shí)現(xiàn)與其他系統(tǒng)的數(shù)據(jù)交互,提高系統(tǒng)的可擴(kuò)展性和數(shù)據(jù)共享能力,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧
    2023-04-04
  • IDEA2020導(dǎo)入非maven項(xiàng)目并部署tomcat的方法

    IDEA2020導(dǎo)入非maven項(xiàng)目并部署tomcat的方法

    這篇文章主要介紹了IDEA 2020 導(dǎo)入非maven項(xiàng)目并部署tomcat的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • 自定義Spring Security的身份驗(yàn)證失敗處理方法

    自定義Spring Security的身份驗(yàn)證失敗處理方法

    在本篇文章里小編給大家整理了一篇關(guān)于自定義Spring Security的身份驗(yàn)證失敗的處理方法,有需要的朋友們學(xué)習(xí)下。
    2019-05-05
  • IDEA GIT 忽略文件的最佳方式推薦

    IDEA GIT 忽略文件的最佳方式推薦

    這篇文章主要介紹了IDEA GIT 忽略文件的最佳方式推薦,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-01-01
  • java解決Feign異步情況丟失上下文問(wèn)題

    java解決Feign異步情況丟失上下文問(wèn)題

    在微服務(wù)的開(kāi)發(fā)中,我們經(jīng)常需要服務(wù)之間的調(diào)用,本文主要介紹了java解決Feign異步情況丟失上下文問(wèn)題,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-08-08
  • JAVA?POI設(shè)置EXCEL單元格格式用法舉例

    JAVA?POI設(shè)置EXCEL單元格格式用法舉例

    這篇文章主要給大家介紹了關(guān)于JAVA?POI設(shè)置EXCEL單元格格式用法的相關(guān)資料,POI中可能會(huì)用到一些需要設(shè)置EXCEL單元格格式的操作,需要的朋友可以參考下
    2023-08-08
  • Spring深入分析講解BeanUtils的實(shí)現(xiàn)

    Spring深入分析講解BeanUtils的實(shí)現(xiàn)

    java知識(shí)體系統(tǒng)有很多數(shù)據(jù)實(shí)體,比較常用的DTO、BO、DO、VO等,其他類似POJO概念太老了現(xiàn)在基本廢棄掉了,本篇幅直接忽略,對(duì)于這幾種數(shù)據(jù)實(shí)體各自代表的含義和應(yīng)用場(chǎng)景先做一下簡(jiǎn)單描述和分析
    2022-06-06
  • mybatis insert foreach循環(huán)插入方式

    mybatis insert foreach循環(huán)插入方式

    這篇文章主要介紹了mybatis insert foreach循環(huán)插入方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Mybatis使用連表查詢的操作代碼

    Mybatis使用連表查詢的操作代碼

    這篇文章主要介紹了Mybatis如何使用連表查詢,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-08-08

最新評(píng)論