深入淺析Java中的String類(lèi)-創(chuàng)新互聯(lián)

這期內(nèi)容當(dāng)中小編將會(huì)給大家?guī)?lái)有關(guān)深入淺析Java中的String類(lèi),文章內(nèi)容豐富且以專(zhuān)業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

成都創(chuàng)新互聯(lián)制作網(wǎng)站網(wǎng)頁(yè)找三站合一網(wǎng)站制作公司,專(zhuān)注于網(wǎng)頁(yè)設(shè)計(jì),成都做網(wǎng)站、網(wǎng)站建設(shè),網(wǎng)站設(shè)計(jì),企業(yè)網(wǎng)站搭建,網(wǎng)站開(kāi)發(fā),建網(wǎng)站業(yè)務(wù),680元做網(wǎng)站,已為上千余家服務(wù),成都創(chuàng)新互聯(lián)網(wǎng)站建設(shè)將一如既往的為我們的客戶(hù)提供最優(yōu)質(zhì)的網(wǎng)站建設(shè)、網(wǎng)絡(luò)營(yíng)銷(xiāo)推廣服務(wù)!

引題

在Java語(yǔ)言的所有數(shù)據(jù)類(lèi)型中,String類(lèi)型是比較特殊的一種類(lèi)型,同時(shí)也是面試的時(shí)候經(jīng)常被問(wèn)到的一個(gè)知識(shí)點(diǎn),本文結(jié)合Java內(nèi)存分配深度分析關(guān)于String的許多令人迷惑的問(wèn)題。下面是本文將要涉及到的一些問(wèn)題,如果讀者對(duì)這些問(wèn)題都了如指掌,則可忽略此文。

    1、Java內(nèi)存具體指哪塊內(nèi)存?這塊內(nèi)存區(qū)域?yàn)槭裁匆M(jìn)行劃分?是如何劃分的?劃分之后每塊區(qū)域的作用是什么?如何設(shè)置各個(gè)區(qū)域的大?。?/p>

    2、String類(lèi)型在執(zhí)行連接操作時(shí),效率為什么會(huì)比StringBuffer或者StringBuilder低?StringBuffer和StringBuilder有什么聯(lián)系和區(qū)別?

    3、Java中常量是指什么?String s = "s" 和 String s = new String("s") 有什么不一樣?

    本文經(jīng)多方資料的收集整理和歸納,最終撰寫(xiě)成文,如果有錯(cuò)誤之處,請(qǐng)多多指教!

Java內(nèi)存分配

    1、JVM簡(jiǎn)介

      Java虛擬機(jī)(Java Virtual Machine 簡(jiǎn)稱(chēng)JVM)是運(yùn)行所有Java程序的抽象計(jì)算機(jī),是Java語(yǔ)言的運(yùn)行環(huán)境,它是Java 最具吸引力的特性之一。Java虛擬機(jī)有自己完善的硬體架構(gòu),如處理器、堆棧、寄存器等,還具有相應(yīng)的指令系統(tǒng)。JVM屏蔽了與具體操作系統(tǒng)平臺(tái)相關(guān)的信息,使得Java程序只需生成在Java虛擬機(jī)上運(yùn)行的目標(biāo)代碼(字節(jié)碼),就可以在多種平臺(tái)上不加修改地運(yùn)行。

            一個(gè)運(yùn)行時(shí)的Java虛擬機(jī)實(shí)例的天職是:負(fù)責(zé)運(yùn)行一個(gè)java程序。當(dāng)啟動(dòng)一個(gè)Java程序時(shí),一個(gè)虛擬機(jī)實(shí)例也就誕生了。當(dāng)該程序關(guān)閉退出,這個(gè)虛擬機(jī)實(shí)例也就隨之消亡。如果同一臺(tái)計(jì)算機(jī)上同時(shí)運(yùn)行三個(gè)Java程序,將得到三個(gè)Java虛擬機(jī)實(shí)例。每個(gè)Java程序都運(yùn)行于它自己的Java虛擬機(jī)實(shí)例中。

        如下圖所示,JVM的體系結(jié)構(gòu)包含幾個(gè)主要的子系統(tǒng)和內(nèi)存區(qū):

             垃圾回收器(Garbage Collection):負(fù)責(zé)回收堆內(nèi)存(Heap)中沒(méi)有被使用的對(duì)象,即這些對(duì)象已經(jīng)沒(méi)有被引用了。

             類(lèi)裝載子系統(tǒng)(Classloader Sub-System):除了要定位和導(dǎo)入二進(jìn)制class文件外,還必須負(fù)責(zé)驗(yàn)證被導(dǎo)入類(lèi)的正確性,為類(lèi)變量分配并初始化內(nèi)存,以及幫助解析符號(hào)引用。

             執(zhí)行引擎(Execution Engine):負(fù)責(zé)執(zhí)行那些包含在被裝載類(lèi)的方法中的指令。

             運(yùn)行時(shí)數(shù)據(jù)區(qū)(Java Memory Allocation Area):又叫虛擬機(jī)內(nèi)存或者Java內(nèi)存,虛擬機(jī)運(yùn)行時(shí)需要從整個(gè)計(jì)算機(jī)內(nèi)存劃分一塊內(nèi)存區(qū)域存儲(chǔ)許多東西。例如:字節(jié)碼、從已裝載的class文件中得到的其他信息、程序創(chuàng)建的對(duì)象、傳遞給方法的參數(shù),返回值、局部變量等等。

深入淺析Java中的String類(lèi)

    2、Java內(nèi)存分區(qū)

      從上節(jié)知道,運(yùn)行時(shí)數(shù)據(jù)區(qū)即是java內(nèi)存,而且數(shù)據(jù)區(qū)要存儲(chǔ)的東西比較多,如果不對(duì)這塊內(nèi)存區(qū)域進(jìn)行劃分管理,會(huì)顯得比較雜亂無(wú)章。程序喜歡有規(guī)律的東西,最討厭雜亂無(wú)章的東西。 根據(jù)存儲(chǔ)數(shù)據(jù)的不同,java內(nèi)存通常被劃分為5個(gè)區(qū)域:程序計(jì)數(shù)器(Program Count Register)、本地方法棧(Native Stack)、方法區(qū)(Methon Area)、棧(Stack)、堆(Heap)。

      程序計(jì)數(shù)器(Program Count Register):又叫程序寄存器。JVM支持多個(gè)線(xiàn)程同時(shí)運(yùn)行,當(dāng)每一個(gè)新線(xiàn)程被創(chuàng)建時(shí),它都將得到它自己的PC寄存器(程序計(jì)數(shù)器)。如果線(xiàn)程正在執(zhí)行的是一個(gè)Java方法(非native),那么PC寄存器的值將總是指向下一條將被執(zhí)行的指令,如果方法是 native的,程序計(jì)數(shù)器寄存器的值不會(huì)被定義。 JVM的程序計(jì)數(shù)器寄存器的寬度足夠保證可以持有一個(gè)返回地址或者native的指針。            

     棧(Stack):又叫堆棧。JVM為每個(gè)新創(chuàng)建的線(xiàn)程都分配一個(gè)棧。也就是說(shuō),對(duì)于一個(gè)Java程序來(lái)說(shuō),它的運(yùn)行就是通過(guò)對(duì)棧的操作來(lái)完成的。棧以幀為單位保存線(xiàn)程的狀態(tài)。JVM對(duì)棧只進(jìn)行兩種操作:以幀為單位的壓棧和出棧操作。我們知道,某個(gè)線(xiàn)程正在執(zhí)行的方法稱(chēng)為此線(xiàn)程的當(dāng)前方法。我們可能不知道,當(dāng)前方法使用的幀稱(chēng)為當(dāng)前幀。當(dāng)線(xiàn)程激活一個(gè)Java方法,JVM就會(huì)在線(xiàn)程的 Java堆棧里新壓入一個(gè)幀,這個(gè)幀自然成為了當(dāng)前幀。在此方法執(zhí)行期間,這個(gè)幀將用來(lái)保存參數(shù)、局部變量、中間計(jì)算過(guò)程和其他數(shù)據(jù)。從Java的這種分配機(jī)制來(lái)看,堆棧又可以這樣理解:棧(Stack)是操作系統(tǒng)在建立某個(gè)進(jìn)程時(shí)或者線(xiàn)程(在支持多線(xiàn)程的操作系統(tǒng)中是線(xiàn)程)為這個(gè)線(xiàn)程建立的存儲(chǔ)區(qū)域,該區(qū)域具有先進(jìn)后出的特性。其相關(guān)設(shè)置參數(shù):

• -Xss --設(shè)置方法棧的大值

          本地方法棧(Native Stack):存儲(chǔ)本地方方法的調(diào)用狀態(tài)。 

深入淺析Java中的String類(lèi)

          方法區(qū)(Method Area):當(dāng)虛擬機(jī)裝載一個(gè)class文件時(shí),它會(huì)從這個(gè)class文件包含的二進(jìn)制數(shù)據(jù)中解析類(lèi)型信息,然后把這些類(lèi)型信息(包括類(lèi)信息、常量、靜態(tài)變量等)放到方法區(qū)中,該內(nèi)存區(qū)域被所有線(xiàn)程共享,如下圖所示。本地方法區(qū)存在一塊特殊的內(nèi)存區(qū)域,叫常量池(Constant Pool),這塊內(nèi)存將與String類(lèi)型的分析密切相關(guān)。

深入淺析Java中的String類(lèi)

         (Heap):Java堆(Java Heap)是Java虛擬機(jī)所管理的內(nèi)存中大的一塊。Java堆是被所有線(xiàn)程共享的一塊內(nèi)存區(qū)域。在此區(qū)域的唯一目的就是存放對(duì)象實(shí)例,幾乎所有的對(duì)象實(shí)例都是在這里分配內(nèi)存,但是這個(gè)對(duì)象的引用卻是在棧(Stack)中分配。因此,執(zhí)行String s = new String("s")時(shí),需要從兩個(gè)地方分配內(nèi)存:在堆中為String對(duì)象分配內(nèi)存,
在棧中為引用(這個(gè)堆對(duì)象的內(nèi)存地址,即指針)分配內(nèi)存,如下圖所示。

深入淺析Java中的String類(lèi)

            JAVA虛擬機(jī)有一條在堆中分配新對(duì)象的指令,卻沒(méi)有釋放內(nèi)存的指令,正如你無(wú)法用Java代碼區(qū)明確釋放一個(gè)對(duì)象一樣。虛擬機(jī)自己負(fù)責(zé)決定如何以及何時(shí)釋放不再被運(yùn)行的程序引用的對(duì)象所占據(jù)的內(nèi)存,通常,虛擬機(jī)把這個(gè)任務(wù)交給垃圾收集器(Garbage Collection)。其相關(guān)設(shè)置參數(shù):

• -Xms -- 設(shè)置堆內(nèi)存初始大小

• -Xmx -- 設(shè)置堆內(nèi)存大值

• -XX:MaxTenuringThreshold -- 設(shè)置對(duì)象在新生代中存活的次數(shù)

• -XX:PretenureSizeThreshold -- 設(shè)置超過(guò)指定大小的大對(duì)象直接分配在舊生代中

        Java堆是垃圾收集器管理的主要區(qū)域,因此又稱(chēng)為“GC 堆”(Garbage Collectioned Heap)。現(xiàn)在的垃圾收集器基本都是采用的分代收集算法,所以Java堆還可以細(xì)分為:新生代(Young Generation)和老年代(Old Generation),如下圖所示。分代收集算法的思想:第一種說(shuō)法,用較高的頻率對(duì)年輕的對(duì)象(young generation)進(jìn)行掃描和回收,這種叫做minor collection,而對(duì)老對(duì)象(old generation)的檢查回收頻率要低很多,稱(chēng)為major collection。這樣就不需要每次GC都將內(nèi)存中所有對(duì)象都檢查一遍,以便讓出更多的系統(tǒng)資源供應(yīng)用系統(tǒng)使用;另一種說(shuō)法,在分配對(duì)象遇到內(nèi)存不足時(shí),先對(duì)新生代進(jìn)行GC(Young GC);當(dāng)新生代GC之后仍無(wú)法滿(mǎn)足內(nèi)存空間分配需求時(shí), 才會(huì)對(duì)整個(gè)堆空間以及方法區(qū)進(jìn)行GC(Full GC)。

深入淺析Java中的String類(lèi)

        在這里可能會(huì)有讀者表示疑問(wèn):記得還有一個(gè)什么永久代(Permanent Generation)的啊,難道它不屬于Java堆?親,你答對(duì)了!其實(shí)傳說(shuō)中的永久代就是上面所說(shuō)的方法區(qū),存放的都是jvm初始化時(shí)加載器加載的一些類(lèi)型信息(包括類(lèi)信息、常量、靜態(tài)變量等),這些信息的生存周期比較長(zhǎng),GC不會(huì)在主程序運(yùn)行期對(duì)PermGen Space進(jìn)行清理,所以如果你的應(yīng)用中有很多CLASS的話(huà),就很可能出現(xiàn)PermGen Space錯(cuò)誤。其相關(guān)設(shè)置參數(shù):

• -XX:PermSize --設(shè)置Perm區(qū)的初始大小

• -XX:MaxPermSize --設(shè)置Perm區(qū)的大值

         新生代(Young Generation)又分為:Eden區(qū)和Survivor區(qū),Survivor區(qū)有分為From Space和To Space。Eden區(qū)是對(duì)象最初分配到的地方;默認(rèn)情況下,F(xiàn)rom Space和To Space的區(qū)域大小相等。JVM進(jìn)行Minor GC時(shí),將Eden中還存活的對(duì)象拷貝到Survivor區(qū)中,還會(huì)將Survivor區(qū)中還存活的對(duì)象拷貝到Tenured區(qū)中。在這種GC模式下,JVM為了提升GC效率, 將Survivor區(qū)分為From Space和To Space,這樣就可以將對(duì)象回收和對(duì)象晉升分離開(kāi)來(lái)。新生代的大小設(shè)置有2個(gè)相關(guān)參數(shù):

• -Xmn -- 設(shè)置新生代內(nèi)存大小。

• -XX:SurvivorRatio -- 設(shè)置Eden與Survivor空間的大小比例

            老年代(Old Generation): 當(dāng) OLD 區(qū)空間不夠時(shí), JVM 會(huì)在 OLD 區(qū)進(jìn)行 major collection ;完全垃圾收集后,若Survivor及OLD區(qū)仍然無(wú)法存放從Eden復(fù)制過(guò)來(lái)的部分對(duì)象,導(dǎo)致JVM無(wú)法在Eden區(qū)為新對(duì)象創(chuàng)建內(nèi)存區(qū)域,則出現(xiàn)"Out of memory錯(cuò)誤"  。

三、String類(lèi)型的深度解析

    讓我們從Java數(shù)據(jù)類(lèi)型開(kāi)始說(shuō)起吧!Java數(shù)據(jù)類(lèi)型通常(分類(lèi)方法多種多樣)從整體上可以分為兩大類(lèi):基礎(chǔ)類(lèi)型和引用類(lèi)型,基礎(chǔ)類(lèi)型的變量持有原始值,引用類(lèi)型的變量通常表示的是對(duì)實(shí)際對(duì)象的引用,其值通常為對(duì)象的內(nèi)存地址。     

    1、String的本質(zhì)

           打開(kāi)String的源碼,類(lèi)注釋中有這么一段話(huà)“Strings are constant; their values cannot be changed after they are created. String buffers support mutable strings.Because String objects are immutable they can be shared.”。這句話(huà)總結(jié)歸納了String的一個(gè)最重要的特點(diǎn):String是值不可變(immutable)的常量,是線(xiàn)程安全的(can be shared)。

       接下來(lái),String類(lèi)使用了final修飾符,表明了String類(lèi)的第二個(gè)特點(diǎn):String類(lèi)是不可繼承的。

       下面是String類(lèi)的成員變量定義,從類(lèi)的實(shí)現(xiàn)上闡明了String值是不可變的(immutable)。   

 private final char value[];
  private final int count;

分享題目:深入淺析Java中的String類(lèi)-創(chuàng)新互聯(lián)
當(dāng)前路徑:http://muchs.cn/article10/dpdggo.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供域名注冊(cè)、網(wǎng)站排名手機(jī)網(wǎng)站建設(shè)、商城網(wǎng)站、網(wǎng)站制作營(yíng)銷(xiāo)型網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(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)

綿陽(yáng)服務(wù)器托管