JVM中的常量池


在Java的內存分配中,總共3種常量池:

ref:https://blog.csdn.net/zm13007310400/article/details/77534349

1.字符串常量池(String Constant Pool):

1.1:字符串常量池在Java內存區域的哪個位置?

  • 在JDK6.0及之前版本,字符串常量池是放在Perm Gen區(也就是方法區)中;
  • 在JDK7.0版本,字符串常量池被移到了堆中了。至於為什么移到堆內,大概是由於方法區的內存空間太小了。
  • JDK8以后也還是放在了Heap空間中,並沒有已到元空間。

1.2:字符串常量池是什么?

  • 在HotSpot VM里實現的string pool功能的是一個StringTable類,它是一個Hash表,默認值大小長度是1009;這個StringTable在每個HotSpot VM的實例只有一份,被所有的類共享。字符串常量由一個一個字符組成,放在了StringTable上。
  • 在JDK6.0中,StringTable的長度是固定的,長度就是1009,因此如果放入String Pool中的String非常多,就會造成hash沖突,導致鏈表過長,當調用String#intern()時會需要到鏈表上一個一個找,從而導致性能大幅度下降;
  • 在JDK7.0中,StringTable的長度可以通過參數指定:
-XX:StringTableSize=66666
  • 1

1.3:字符串常量池里放的是什么?

  • 在JDK6.0及之前版本中,String Pool里放的都是字符串常量;
  • 在JDK7.0中,由於String#intern()發生了改變,因此String Pool中也可以存放放於堆內的字符串對象的引用。關於String在內存中的存儲和String#intern()方法的說明,可以參考我的另外一篇博客:

需要說明的是:字符串常量池中的字符串只存在一份! 
如:

String s1 = "hello,world!"; String s2 = "hello,world!";
  • 1
  • 2

即執行完第一行代碼后,常量池中已存在 “hello,world!”,那么 s2不會在常量池中申請新的空間,而是直接把已存在的字符串內存地址返回給s2。(這里具體的字符串如何分配就不細說了,可以看我的另一篇博客)

2.class常量池(Class Constant Pool):

2.1:class常量池簡介:

  • 我們寫的每一個Java類被編譯后,就會形成一份class文件;class文件中除了包含類的版本、字段、方法、接口等描述信息外,還有一項信息就是常量池(constant pool table),用於存放編譯器生成的各種字面量(Literal)和符號引用(Symbolic References);
  • 每個class文件都有一個class常量池。

2.2:什么是字面量和符號引用:

  • 字面量包括:1.文本字符串 2.八種基本類型的值 3.被聲明為final的常量等;
  • 符號引用包括:1.類和方法的全限定名 2.字段的名稱和描述符 3.方法的名稱和描述符。

3.運行時常量池(Runtime Constant Pool):

  • 運行時常量池存在於內存中,也就是class常量池被加載到內存之后的版本,不同之處是:它的字面量可以動態的添加(String#intern()),符號引用可以被解析為直接引用
  • JVM在執行某個類的時候,必須經過加載、連接、初始化,而連接又包括驗證、准備、解析三個階段。而當類加載到內存中后,jvm就會將class常量池中的內容存放到運行時常量池中,由此可知,運行時常量池也是每個類都有一個。在解析階段,會把符號引用替換為直接引用,解析的過程會去查詢字符串常量池,也就是我們上面所說的StringTable,以保證運行時常量池所引用的字符串與字符串常量池中是一致的。

 

public static void main(String[] args) {
		String s1="abc";
		String s2="abc";
		System.out.println(s1==s2);//true
		String s3=new String("ab")+new String("c");
		//s3.intern();		
		System.out.println(s1==s3);	//false
		
		String s4=new String("ab")+new String("cd");
		//s4.intern();
		String s5="abcd";
		System.out.println(s4==s5);//true,去掉intern之后是false;
		
	}

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM