一、垃圾回收
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://tech.souyunku.com/zhai1997/p/12599306.html)
串池相关的字符串操作、intern方法:(https://tech.souyunku.com/zhai1997/p/12855383.html)