一、垃圾回收
1、StringTable中存儲的雖然是字符串常量,依舊會被垃圾回收
(1)書寫程序
public class test1804 { public static void main(String[] args) { int i=0; try{ }catch (Throwable e){ e.printStackTrace(); } System.out.println(i); } }
(2)參數
(3)運行結果
內存占用情況:
Heap
PSYoungGen total 2560K, used 1694K [0x00000000ffd00000, 0x0000000100000000, 0x0000000100000000)
eden space 2048K, 82% used [0x00000000ffd00000,0x00000000ffea7838,0x00000000fff00000)
from space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
to space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
ParOldGen total 7168K, used 0K [0x00000000ff600000, 0x00000000ffd00000, 0x00000000ffd00000)
object space 7168K, 0% used [0x00000000ff600000,0x00000000ff600000,0x00000000ffd00000)
Metaspace used 3027K, capacity 4496K, committed 4864K, reserved 1056768K
class space used 325K, capacity 388K, committed 512K, reserved 1048576K
符號表:
SymbolTable statistics:
Number of buckets : 20011 = 160088 bytes, avg 8.000
Number of entries : 12835 = 308040 bytes, avg 24.000
Number of literals : 12835 = 553304 bytes, avg 43.109
Total footprint : = 1021432 bytes
Average bucket size : 0.641
Variance of bucket size : 0.641
Std. dev. of bucket size: 0.801
Maximum bucket size : 6
StringTable(Hash表的方式存儲數據):
StringTable statistics: Number of buckets : 60013 = 480104 bytes, avg 8.000 Number of entries : 1772 = 42528 bytes, avg 24.000 Number of literals : 1772 = 158584 bytes, avg 89.494 Total footprint : = 681216 bytes Average bucket size : 0.030 Variance of bucket size : 0.030 Std. dev. of bucket size: 0.172 Maximum bucket size : 3
類名、方法名等信息也是以字符串常量的方式存儲的,因此才會顯示1720個字符串
(4)修改程序重新查看StringTable
程序:
public class test1804 { public static void main(String[] args) { int i=0; try{ for(int j=0;j<=100;j++){ String.valueOf(j).intern(); i++; } }catch (Throwable e){ e.printStackTrace(); } System.out.println(i); } }
StringTable:
StringTable statistics: Number of buckets : 60013 = 480104 bytes, avg 8.000 Number of entries : 1872 = 44928 bytes, avg 24.000 Number of literals : 1872 = 163384 bytes, avg 87.278 Total footprint : = 688416 bytes Average bucket size : 0.031 Variance of bucket size : 0.031 Std. dev. of bucket size: 0.177 Maximum bucket size : 3
可以看到字符串的數量正好增多100個字符串對象,與for循環創建的字符串數量一致
(5)增大for循環的次數
public class test1804 { public static void main(String[] args) { int i=0; try{ for(int j=0;j<10000;j++){ String.valueOf(j).intern(); i++; } }catch (Throwable e){ e.printStackTrace(); } System.out.println(i); } }
發生了垃圾回收,這也就是StringTable沒有增加10000個字符串對象的原因:
[GC (Allocation Failure) [PSYoungGen: 2048K->488K(2560K)] 2048K->712K(9728K), 0.0016286 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
StringTable:
StringTable statistics: Number of buckets : 60013 = 480104 bytes, avg 8.000 Number of entries : 6615 = 158760 bytes, avg 24.000 Number of literals : 6615 = 391128 bytes, avg 59.127 Total footprint : = 1029992 bytes Average bucket size : 0.110 Variance of bucket size : 0.111 Std. dev. of bucket size: 0.333 Maximum bucket size : 3
二、性能調優
1、StringTableSize
jvm的默認桶的大小:
Number of buckets : 60013 = 480104 bytes, avg 8.000
添加參數增加桶的個數(最小值可以設置為1009):
-XX StringTableSize=200000
減少桶的沖突,可以提高jvm的效率
2、考慮字符串對象是否入池
運用intern方法將字符串入池,保證相同的字符串只存儲一份(在串池中如果已經有相同的字符串對象就不會再創建該字符串對象了)
相關內容:
jvm的堆內存:(https://www.cnblogs.com/zhai1997/p/12599306.html)
串池相關的字符串操作、intern方法:(https://www.cnblogs.com/zhai1997/p/12855383.html)