全局变量直接声明(包含静态变量) private static final String STR1 = "world"
局部变量直接申明 String str = "hello";
程序中动态生成 拼接,读取DB,读取文件等行为
首先使用一个空Main方法,增加-XX:+PrintStringTableStatistics参数,在IDEA JDK8下,我电脑运行的输出Number of entries一直是840,那么这个就是基础数据了。
1 2 3 4 5 6 7 8 9 10
# 代码 publicclassMain { publicstaticvoidmain(String[] args) { } } # 输出 StringTable statistics: Number of buckets : 60013 = 480104 bytes, avg 8.000 Number of entries : 840 = 20160 bytes, avg 24.000 Number of literals : 840 = 57584 bytes, avg 68.552
增加局部变量后,常量池大小+1
1 2 3 4 5 6 7 8 9 10 11
# 代码 publicclassMain { publicstaticvoidmain(String[] args) { Stringstr1="hello"; } } # 输出 StringTable statistics: Number of buckets : 60013 = 480104 bytes, avg 8.000 Number of entries : 841 = 20184 bytes, avg 24.000 Number of literals : 841 = 57640 bytes, avg 68.537
增加静态变量,常量池大小+1
1 2 3 4 5 6 7 8 9 10 11 12
# 代码 publicclassMain { privatestaticfinalStringSTR="world"; publicstaticvoidmain(String[] args) { Stringstr1="hello"; } } # 输出 StringTable statistics: Number of buckets : 60013 = 480104 bytes, avg 8.000 Number of entries : 842 = 20208 bytes, avg 24.000 Number of literals : 842 = 57696 bytes, avg 68.523
动态拼接,常量池不变
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
# 代码 publicclassMain { privatestaticfinalStringSTR="world"; publicstaticvoidmain(String[] args) { Stringstr1="hello"; for (inti=0; i < 10; i++) { Stringtemp= Integer.toString(i); } } } # 输出 StringTable statistics: Number of buckets : 60013 = 480104 bytes, avg 8.000 Number of entries : 842 = 20208 bytes, avg 24.000 Number of literals : 842 = 57696 bytes, avg 68.523
动态拼接,增加intern调用,常量池+10
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
# 代码 publicclassMain { privatestaticfinalStringSTR="world"; publicstaticvoidmain(String[] args) { Stringstr1="hello"; for (inti=0; i < 10; i++) { Stringtemp= Integer.toString(i).intern(); } } } # 输出 StringTable statistics: Number of buckets : 60013 = 480104 bytes, avg 8.000 Number of entries : 852 = 20448 bytes, avg 24.000 Number of literals : 852 = 58176 bytes, avg 68.282
那么从我这个不专业的测试,可以得出结论,如有疑议可以评论中讨论哈。
字面字符串常量会进入到字符串常量池
代码中动态生成的字符串不会进入常量池
intern可以主动让字符串进入常量池
常见问题解释
1.String str4 = new String(“abc”)执行过程?
通过反编译以及常量池输出,可以看出结论,常量池+1,不包括常量池的话,对象也是+1,流程是先创建(new)一个String对象,压入(dup)到栈顶,然后从常量池中(ldc)初始化abd字符串,调用构造函数初始化(invokespecial)对象,最后将对象引用赋值(astore_1)给本地变量str4。反编译插件可以使用IDEA插件 – Class Decompile
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
# 反编译结果 publicstaticvoidmain(java.lang.String[]); Code: 0: new #2// class java/lang/String 3: dup 4: ldc #3// String abc 6: invokespecial #4// Method java/lang/String."<init>":(Ljava/lang/String;)V 9: astore_1 10: return } # 常量池输出 StringTable statistics: Number of buckets : 60013 = 480104 bytes, avg 8.000 Number of entries : 841 = 20184 bytes, avg 24.000 Number of literals : 841 = 57632 bytes, avg 68.528