JVM中的幾種常量池

點擊查看原文中具體案例與解釋

目錄

一、class文件常量池

字面量

1、文本字符串:

2、被final修飾的變量。

符號引用

1、類和接口和全限定名:

2、字段的名稱和描述符:

3、方法的名稱和描述符。

二、運行時常量池

三、字符串常量池

四、java基本類型封裝類的常量池

補充:t.intern()的用法


一、class文件常量池

在Class文件中除了有類的版本、字段、方法、接口等描述信息外,還有一項信息是常量池(Constant Pool Table),用於存放編譯期生成的各種字面量和符號引用。

這裏簡單解釋下字面量和符號引用

字面量

字面量類似與我們平常說的常量,主要包括:

1、文本字符串:

就是我們在代碼中能夠看到的字符串,例如String a = “aa”。其中”aa”就是字面量。

2、被final修飾的變量。

符號引用

主要包括以下常量:

1、類和接口和全限定名:

例如對於String這個類,它的全限定名就是java/lang/String。

2、字段的名稱和描述符:

所謂字段就是類或者接口中聲明的變量,包括類級別變量(static)和實例級的變量。

3、方法的名稱和描述符。

所謂描述符就相當於方法的參數類型+返回值類型

二、運行時常量池

我們上面說的class文件中的常量池,它會在類加載後進入方法區中的運行時常量池。並且需要的注意的是,運行時常量池是全局共享的,多個類共用一個運行時常量池。並且class文件中常量池多個相同的字符串在運行時常量池只會存在一份。

注意運行時常量池存在於方法區中。

三、字符串常量池

看名字我們就可以知道字符串常量池會用來存放字符串,也就是說常量池中的文本字符串會在類加載時進入字符串常量池。

那字符串常量池和運行時常量池是什麼關係呢?上面我們說常量池中的字面量會在類加載後進入運行時常量池,其中字面量中有包括文本字符串,顯然從這段文字我們可以知道字符串常量池存在於運行時常量池中。也就存在於方法區中。

不過在周志明那本深入java虛擬機中有說到,到了JDK1.7時,字符串常量池就被移出了方法區,轉移到了裏了。

那麼我們可以推斷,到了JDK1.7以及之後的版本中,運行時常量池並沒有包含字符串常量池,運行時常量池存在於方法區中,而字符串常量池存在於中。

四、java基本類型封裝類的常量池

1. 內存中有一個java基本類型封裝類的常量池。這些類包括
Byte, Short, Integer, Long, Character, Boolean。需要注意的是,Float和Double這兩個類並沒有對應的常量池。

2.上面5種整型的包裝類也只是在對象數值在-128~127纔可以使用這些常量池。

3. 在周志明的那本虛擬機中有這樣一句話:包裝類的
“\==”運行符在不遇到算術運算的情況下不會自動拆箱,以及他們的equals()方法不處理數據類型的關係,可以推斷出如果遇到“==”兩邊有算術運算是話就會自動拆箱和進行數據類型轉換處理。

4.Long的equals方法會先判斷是否是Long類型。

5.無論是Integer還是Long,他們的equals方法比較的是數值。

補充:t.intern()的用法

String t = "tt";

例如我們調用了t.intern()

在JDK1.6的時候,調用了這個方法之後,虛擬機會在字符串常量池在查找是否有內容與”tt”相等的對象,如果有,則返回這個對象,如果沒有,則會在字符串常量池中添加這個對象。注意,是把這個對象添加到字符串常量池。

到了JDK1.7之後,如果調用了intern這個方法,虛擬機會在字符串常量池在查找是否有內容與”tt”相等的對象,如果有,則返回這個對象,如果沒有。則會在堆中把這個對象的引用複製添加到字符串常量池中。注意,這個時候添加的是對象在堆中的引用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章