1. 程式人生 > >Java字串在記憶體中的儲存位置

Java字串在記憶體中的儲存位置

在JDK6的時候在Java虛擬機器(這裡指的是HotSpot)中記憶體區域分為本地方法棧、虛擬機器棧、堆、程式計數器、方法區等,方法區又被稱作永久代。
這裡只說一下字串的儲存位置,在Java虛擬機器記憶體中有個區域叫做執行時常量池,是方法區的一部分。在JDK6中其中存放的有類的版本、欄位、方法、介面等描述資訊以及常量池,常量池用來存放編譯期間生成的各種字面量和符號引用,字串就儲存在這個位置。下面通過程式碼來看下現象。

這是JDK6的實驗現象,Java虛擬機器的配置如下:
-XX:PermSize=5M -XX:MaxPermSize=5M -Xms5M -Xmx5M -XX:-UseGCOverheadLimit -verbose:gc
其含義是方法區的初始大小為5M,最大為5M;堆空間的初始大小為5M,最大為5M,當垃圾回收時間佔的比例較高時不允許報錯,列印垃圾回收資訊。

import java.util.ArrayList;
import java.util.List;

public class StringTest {


    static String base = "string";

    public static void main(String[] args) {
        List list = new ArrayList();
        for (int i = 0; i < Integer.MAX_VALUE; i++) {
            String str = base + base;
            base
= str; list.add(str.intern()); } } }

執行錯誤如下:
這裡寫圖片描述
可以看到報的是永久代即方法區的記憶體溢位錯誤,在這裡使用了String API的inner方法,其作用是把首次遇到的字串例項複製到永久代去,返回的也是永久代中這個字串例項的引用。

在JDK7中字串已經從常量池中移除,方法區有被取消掉的趨勢,在JDK7的環境下虛擬機器中使用相同的配置執行以上程式碼,情況如下:
這裡寫圖片描述
我們看到的資訊是Java虛擬機器堆溢位,由此可見在JDK7中字串的儲存位置已經被移到了堆中。

在JDK8的環境下,使用相同的虛擬機器配置資訊,就會報一個錯誤,錯誤如下:
這裡寫圖片描述


指出永久代已經在JDK8中移除。
在JDK8中新出現的記憶體區域叫做元空間,其位於本地記憶體中。我們將JDK8的虛擬機器配置資訊修改為如下:
-Xms5M -Xmx5M -XX:MetaspaceSize=5M -XX:MaxMetaspaceSize=5M -verbose:gc
其含義是堆記憶體的初始大小為5M,最大空間為5M,元空間的初始大小為5M,最大為5M,列印垃圾回收的資訊。
執行遇上相同的程式碼,列印的錯誤資訊如下:
這裡寫圖片描述
可以看到是堆記憶體溢位,在這裡筆者產生一個疑問,因為通過網上看的資料說的是此處應該為元空間溢位的錯誤,但是筆者通過實際的測試發現,其報的錯誤依然是堆記憶體溢位的錯誤,也就是在JDK8中字串的儲存位置是堆?
因為實驗結果跟網上看到的有區別,暫且在這裡打上一個問號。