StringTable結構以及基本調優

  JDK1.8中StringTable的底層相似於HashTable,由數組和鏈表實現,數組又稱爲桶數組。好比有這樣一段代碼:linux

public class Demo4 {
    public static void main(String[] args) {
        int i = 0;
        System.out.println(i);
    }
}

咱們設置虛擬機參數「-Xmx10m -XX:+PrintStringTableStatistics -XX:+PrintGCDetails -verbose:gc「,參數具體的意思是 設置堆內存大小爲10M,輸出StringTableStatistics信息,輸出GC細節。運行代碼控制檯會有相應的輸出,主要看下StringTable部分。默認桶的個數是60013,存儲的字符串對象個數爲1752,串池中字符串常量個數爲也是1752,總的佔用空間約爲0.6M。上面代碼只是輸出i,但串池中常量個數爲1752,那是由於類名、方法名等這些數據也是以常量的形式存在串池中。數組

接着稍微改動代碼:spa

public class Demo4 {
    public static void main(String[] args) {
        int i = 0;
        // 往串池中添加100個字符串
        for (int j = 0; j < 100; j++) {
            String.valueOf(j).intern();
            i++;
        }
        System.out.println(i);
    }
}

這時候咱們能夠看到串池中字符串個數爲1871,比默認多了100個。3d

繼續用上述代碼作實驗,這會for循環次數爲10000,看控制檯輸出有什麼變化。code

字符串個數爲7451並非11751,由於咱們設置了堆內存大小爲10M,存10000個字符串對象的話堆內存發生了MinorGC,將一些無用的對象回收了。對象

調優blog

  • 調優主要是對StringTable大小的設置,若是程序中字符串數量很是多,那麼能夠將桶個數設置大一些,具體參數爲 -XX:StringTableSize = 大小,默認是60013,最小是1009。有這樣一段代碼:
public class Demo5 {
    public static void main(String[] args) throws IOException {
       try (BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("linux.words"), "utf-8"))) {
            String line = null;
            long start = System.nanoTime();
            while (true) {
                line = reader.readLine();
                if (line == null) {
                    break;
                }
                line.intern();
            }
            System.out.println("cost:" + (System.nanoTime() - start) / 1000000);
        }
    }
}

  "linux.words"中有480000個字符串,讀取文件而後將字符串放入串池,記錄整個過程消耗時間,以ms爲單位而且打印信息。默認桶個數下消耗時間爲0.57秒。    內存

        

  咱們設置 -XX:StringTableSize=1009再觀察下消耗時間,變爲了9.852秒。因此可根據業務場景來設置桶個數大小。 utf-8

        

  • 若是應用裏有大量字符串而且存在不少重複的字符串,能夠考慮使用intern()方法將字符串入池,而不是都存在Eden區中,這樣字符串僅會佔用較少的空間。
相關文章
相關標籤/搜索