亚欧色一区w666天堂,色情一区二区三区免费看,少妇特黄A片一区二区三区,亚洲人成网站999久久久综合,国产av熟女一区二区三区

  • 發布文章
  • 消息中心
點贊
收藏
評論
分享
原創

JVM中幾種常量池的分析

2023-05-30 01:12:57
4
0

在JVM的(de)內(nei)存模型中,我們(men)經常聽(ting)到常量(liang)池(chi)的(de)概念,我一開(kai)始(shi)時認為常量(liang)池(chi)就是一塊內(nei)存區域,所(suo)(suo)有常量(liang)存放于其中,最近在學習JVM,看到好幾種常量(liang)池(chi)的(de)說(shuo)法(fa),把自己都搞糊涂了。花了一天(tian)時間,查詢各種資料,所(suo)(suo)幸有所(suo)(suo)頓悟,決定(ding)記錄下(xia)來,方便查閱。

注意本文以JVM8-HotSpot為基準(zhun)。

 

1. 相關知識科普

(1)什么是常量

用(yong)final修飾的(de)成員變(bian)(bian)量(liang)表示(shi)常量(liang),值一旦給定就無法改(gai)變(bian)(bian)!final修飾的(de)變(bian)(bian)量(liang)有三種(zhong):靜態變(bian)(bian)量(liang)(類(lei)變(bian)(bian)量(liang))、實例(li)變(bian)(bian)量(liang)和局部變(bian)(bian)量(liang),分別表示(shi)三種(zhong)類(lei)型的(de)常量(liang)。

(2)為什么使用常(chang)量(liang)池(chi),即(ji)常(chang)量(liang)池(chi)的(de)好(hao)處

常量池是為(wei)了(le)避免頻繁的創(chuang)建和銷毀對(dui)象而(er)影(ying)響系統性能,其實現了(le)對(dui)象的共(gong)享。例如字符(fu)串常量池,在(zai)編譯階段(duan)就把所(suo)有的字符(fu)串字面量放到一(yi)個(ge)常量池中。

  • 節省內存空間:常(chang)量池(chi)中所有相(xiang)同的字(zi)符串常(chang)量被合并(bing),只占用一個空間;

  • 節(jie)省運行時(shi)間:比較(jiao)字符串時(shi),==比equals()快。對于兩個引(yin)用變量,只用==判斷(duan)引(yin)用是否相等,也就可以判斷(duan)實際值是否相等,new出(chu)來的不行。

(3)==的含義

  • 基本數(shu)據類型之間使用==,比較的(de)是(shi)他們的(de)數(shu)值;

  • 引用之間應用(yong)==,比較的是(shi)他們在內存中的存放地址。

2. class文件常量池(class constant pool)

class文件是一組以字節為單位(因此也被稱為字節碼文件)的二進制數據流,我們編寫的.java文件在編譯后生成.class文件,其中就包括class文件常量池。為了方便說明,我們寫個簡單的類。
public class App {
    private String value = "Hello";
    public int id = 110;
    public final static int CONSTANT = 0x110;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        int tmp = id + 1;
        this.id = tmp;
    }
}

使用(yong)javac編譯生成(cheng)App.class,再使用(yong)javap -v App.class 查(cha)看編譯后的(de)內容,這里(li)主要列出常量池(chi)的(de)部分(fen):

Constant pool:
   #1 = Methodref          #6.#29         // java/lang/Object."<init>":()V
   #2 = String             #30            // Hello
   #3 = Fieldref           #5.#31         // com/taylor/test/jvm/App.value:Ljava/lang/String;
   #4 = Fieldref           #5.#32         // com/taylor/test/jvm/App.id:I
   #5 = Class              #33            // com/taylor/test/jvm/App
   #6 = Class              #34            // java/lang/Object
   #7 = Utf8               value
   #8 = Utf8               Ljava/lang/String;
   #9 = Utf8               id
  #10 = Utf8               I
  #11 = Utf8               CONSTANT
  #12 = Utf8               ConstantValue
  #13 = Integer            272
  #14 = Utf8               <init>
  #15 = Utf8               ()V
  #16 = Utf8               Code
  #17 = Utf8               LineNumberTable
  #18 = Utf8               LocalVariableTable
  #19 = Utf8               this
  #20 = Utf8               Lcom/taylor/test/jvm/App;
  #21 = Utf8               getId
  #22 = Utf8               ()I
  #23 = Utf8               setId
  #24 = Utf8               (I)V
  #25 = Utf8               tmp
  #26 = Utf8               MethodParameters
  #27 = Utf8               SourceFile
  #28 = Utf8               App.java
  #29 = NameAndType        #14:#15        // "<init>":()V
  #30 = Utf8               Hello
  #31 = NameAndType        #7:#8          // value:Ljava/lang/String;
  #32 = NameAndType        #9:#10         // id:I
  #33 = Utf8               com/taylor/test/jvm/App
  #34 = Utf8               java/lang/Object

class文件常量池主要存放兩大常量:字面量(Literal)和符號引用(Symbolic References)。

(1) 字面(mian)量:接近java語言層(ceng)面(mian)的常量概(gai)念,主要包括:

  • 文(wen)本字符串(chuan),也就(jiu)是我們(men)經常(chang)聲明的(de):public String value = "Hello";中的(de)"Hello"

    #2 = String             #29            // Hello
    #30 = Utf8               Hello
  • 用final修飾的靜態變(bian)量

    #13 = Integer            272

    強調一下,字面(mian)(mian)(mian)量指的(de)是(shi)數(shu)據的(de)值,即(ji)”Hello“和0x110(272)。通(tong)過上面(mian)(mian)(mian)對常(chang)量池(chi)的(de)觀察(cha),這兩(liang)個(ge)字面(mian)(mian)(mian)值確實(shi)存在于常(chang)量池(chi)中(zhong)。而對于實(shi)例變量,即(ji)上面(mian)(mian)(mian)的(de)public int id = 110,常(chang)量池(chi)只保(bao)留了他(ta)們的(de)字段描述符(fu)I和字段的(de)名稱id,他(ta)們的(de)字面(mian)(mian)(mian)量不(bu)會存在于常(chang)量池(chi)中(zhong)。小朋友(you),你是(shi)不(bu)是(shi)有很多(duo)問號?110去哪里了?答(da)案是(shi),他(ta)們在對應的(de)字節碼方法里:

    public com.taylor.test.jvm.App();
        descriptor: ()V
        flags: ACC_PUBLIC
        Code:
          stack=2, locals=1, args_size=1
             0: aload_0
             1: invokespecial #1                  // Method java/lang/Object."<init>":()V
             4: aload_0
             5: ldc           #2                  // String Hello
             7: putfield      #3                  // Field value:Ljava/lang/String;
            10: aload_0
            11: bipush        110
            13: putfield      #4                  // Field id:I
            16: return?
    第11行對應的 bipush 110

    (2) 符號(hao)引用:主要設(she)涉及(ji)編譯原理(li)方面的概念,包括(kuo)下面三類常量:

    • 類和接口的全限定名,將類名中原(yuan)來(lai)的"."替(ti)換為(wei)"/"得(de)到(dao)的,主要用(yong)于在運行時解析得(de)到(dao)類的直接引用(yong)

       #5 = Class              #27            // com/taylor/test/jvm/App
       #33 = Utf8               com/taylor/test/jvm/App
    • 字段(duan)的名稱(cheng)和描述符(字段(duan)類型),字段(duan)也(ye)就是類或者接口中聲明(ming)的變量,包括(kuo)類變量和實例變量

0條評論
作者已關閉評論
z****n
3文章數
0粉絲數(shu)
z****n
3 文(wen)章 | 0 粉絲
z****n
3文章數(shu)
0粉絲數(shu)
z****n
3 文章(zhang) | 0 粉絲
原創

JVM中幾種常量池的分析

2023-05-30 01:12:57
4
0

在(zai)JVM的內存(cun)模型中,我們經(jing)常(chang)聽到常(chang)量池的概念,我一(yi)(yi)開始時認為(wei)常(chang)量池就是一(yi)(yi)塊內存(cun)區域,所有(you)常(chang)量存(cun)放于其中,最近在(zai)學習JVM,看(kan)到好幾種常(chang)量池的說法,把自(zi)己都搞糊涂(tu)了(le)(le)。花了(le)(le)一(yi)(yi)天(tian)時間,查詢各種資料,所幸有(you)所頓悟,決(jue)定記錄下來,方便(bian)查閱。

注意本文以JVM8-HotSpot為基(ji)準。

 

1. 相關知識科普

(1)什么是常量

用final修飾(shi)的成員(yuan)變(bian)量(liang)表示常(chang)量(liang),值一旦給定就無法改變(bian)!final修飾(shi)的變(bian)量(liang)有三種:靜態變(bian)量(liang)(類變(bian)量(liang))、實例變(bian)量(liang)和局部(bu)變(bian)量(liang),分(fen)別表示三種類型的常(chang)量(liang)。

(2)為什么使用常量池,即常量池的好(hao)處

常量(liang)(liang)池是為了(le)避免(mian)頻繁的(de)(de)創建和銷毀對象而(er)影響系統(tong)性(xing)能(neng),其實現了(le)對象的(de)(de)共享。例如字(zi)(zi)(zi)符串常量(liang)(liang)池,在編(bian)譯階段(duan)就(jiu)把所有(you)的(de)(de)字(zi)(zi)(zi)符串字(zi)(zi)(zi)面量(liang)(liang)放到一個常量(liang)(liang)池中(zhong)。

  • 節省內存空間(jian):常(chang)量池中(zhong)所有相(xiang)同(tong)的字符串(chuan)常(chang)量被合并,只(zhi)占用(yong)一(yi)個空間(jian);

  • 節省運(yun)行時(shi)(shi)間:比較(jiao)字(zi)符串(chuan)時(shi)(shi),==比equals()快。對于兩個(ge)引(yin)用(yong)變量,只用(yong)==判(pan)斷引(yin)用(yong)是否相等(deng),也就可以判(pan)斷實際值是否相等(deng),new出來的不(bu)行。

(3)==的含義

  • 基本(ben)數據(ju)類型(xing)之間使用(yong)==,比較的(de)是他們的(de)數值;

  • 引用(yong)之間應用(yong)==,比較(jiao)的是他們在內存中的存放(fang)地址。

2. class文件常量池(class constant pool)

class文件是一組以字節為單位(因此也被稱為字節碼文件)的二進制數據流,我們編寫的.java文件在編譯后生成.class文件,其中就包括class文件常量池。為了方便說明,我們寫個簡單的類。
public class App {
    private String value = "Hello";
    public int id = 110;
    public final static int CONSTANT = 0x110;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        int tmp = id + 1;
        this.id = tmp;
    }
}

使用javac編譯(yi)生成(cheng)App.class,再使用javap -v App.class 查看編譯(yi)后(hou)的內容(rong),這里主要列出(chu)常量池的部分:

Constant pool:
   #1 = Methodref          #6.#29         // java/lang/Object."<init>":()V
   #2 = String             #30            // Hello
   #3 = Fieldref           #5.#31         // com/taylor/test/jvm/App.value:Ljava/lang/String;
   #4 = Fieldref           #5.#32         // com/taylor/test/jvm/App.id:I
   #5 = Class              #33            // com/taylor/test/jvm/App
   #6 = Class              #34            // java/lang/Object
   #7 = Utf8               value
   #8 = Utf8               Ljava/lang/String;
   #9 = Utf8               id
  #10 = Utf8               I
  #11 = Utf8               CONSTANT
  #12 = Utf8               ConstantValue
  #13 = Integer            272
  #14 = Utf8               <init>
  #15 = Utf8               ()V
  #16 = Utf8               Code
  #17 = Utf8               LineNumberTable
  #18 = Utf8               LocalVariableTable
  #19 = Utf8               this
  #20 = Utf8               Lcom/taylor/test/jvm/App;
  #21 = Utf8               getId
  #22 = Utf8               ()I
  #23 = Utf8               setId
  #24 = Utf8               (I)V
  #25 = Utf8               tmp
  #26 = Utf8               MethodParameters
  #27 = Utf8               SourceFile
  #28 = Utf8               App.java
  #29 = NameAndType        #14:#15        // "<init>":()V
  #30 = Utf8               Hello
  #31 = NameAndType        #7:#8          // value:Ljava/lang/String;
  #32 = NameAndType        #9:#10         // id:I
  #33 = Utf8               com/taylor/test/jvm/App
  #34 = Utf8               java/lang/Object

class文件常量池主要存放兩大常量:字面量(Literal)和符號引用(Symbolic References)。

(1) 字面量:接近java語言(yan)層面的(de)常量概(gai)念,主要包(bao)括:

  • 文本字符串(chuan),也就是我們經常(chang)聲明的(de):public String value = "Hello";中的(de)"Hello"

    #2 = String             #29            // Hello
    #30 = Utf8               Hello
  • 用final修(xiu)飾的靜態變量(liang)

    #13 = Integer            272

    強調一下,字(zi)(zi)面(mian)量(liang)指的(de)是數據的(de)值(zhi),即”Hello“和0x110(272)。通過上面(mian)對常(chang)量(liang)池的(de)觀(guan)察(cha),這(zhe)兩個字(zi)(zi)面(mian)值(zhi)確實(shi)存(cun)在于(yu)常(chang)量(liang)池中(zhong)。而對于(yu)實(shi)例變量(liang),即上面(mian)的(de)public int id = 110,常(chang)量(liang)池只(zhi)保留了(le)他們的(de)字(zi)(zi)段(duan)描述符(fu)I和字(zi)(zi)段(duan)的(de)名(ming)稱(cheng)id,他們的(de)字(zi)(zi)面(mian)量(liang)不會存(cun)在于(yu)常(chang)量(liang)池中(zhong)。小朋友,你是不是有很(hen)多問號(hao)?110去哪里了(le)?答案是,他們在對應的(de)字(zi)(zi)節碼方法里:

    public com.taylor.test.jvm.App();
        descriptor: ()V
        flags: ACC_PUBLIC
        Code:
          stack=2, locals=1, args_size=1
             0: aload_0
             1: invokespecial #1                  // Method java/lang/Object."<init>":()V
             4: aload_0
             5: ldc           #2                  // String Hello
             7: putfield      #3                  // Field value:Ljava/lang/String;
            10: aload_0
            11: bipush        110
            13: putfield      #4                  // Field id:I
            16: return?
    第11行對應的 bipush 110

    (2) 符號引用:主要設涉及(ji)編(bian)譯原理(li)方面的概念,包括下面三(san)類常(chang)量:

    • 類(lei)和接口的全(quan)限定名,將類(lei)名中原來的"."替換為(wei)"/"得到的,主要(yao)用于在(zai)運行時解析(xi)得到類(lei)的直接引用

       #5 = Class              #27            // com/taylor/test/jvm/App
       #33 = Utf8               com/taylor/test/jvm/App
    • 字(zi)段的名(ming)稱和(he)描(miao)述符(字(zi)段類(lei)型(xing)),字(zi)段也就是類(lei)或者接口中聲明的變量(liang),包(bao)括類(lei)變量(liang)和(he)實例變量(liang)

文章來自個人專欄
文章 | 訂(ding)閱
0條評論
作者已關閉評論
作者已關閉評論
0
0