一 点睛
-
字符串常量池是不会存储相同内容的字符串的。
-
String 的 String Pool是一个固定大小的 Hashtable,默认值大小长度是1009。如果放进 String Pool 的 String非常多,就会造成 Hash 冲突严重,从而导致链表会很长,而链表长了后直接会造成的影响就是当调用string.intern时性能会大幅下降。
-
使用 -XX:StringTableSize 可设置 StringTable 的长度
-
在 JDK6 中 StringTable是固定的,就是1009的长度,所以如果常量池中的字符串过多就会导致效率下降很快。StringTablesize 设置没有要求。
-
在 JDK7 中,StringTable 的长度默认值是 60013。
-
在 JDK8 中,StringTable 可以设置的最小值为1009。
二 实战——StringTableSize值测试
1 代码
/**
* 测试 StringTableSize
* -XX:StringTableSize=1009
*/
public class StringTest2 {
public static void main(String[] args) {
// 测试StringTableSize 参数
System.out.println("我来打个酱油");
try {
Thread.sleep(1000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
2 JDK6下运行后测试默认值
E:\JVMDemo>jps
1796 Jps
13976
3832 StringTest2
7756 Launcher
E:\JVMDemo>jinfo -flag StringTableSize 3832
-XX:StringTableSize=1009
3 JDK6 下修改为 -XX:StringTableSize=10
E:\JVMDemo>jps
9664 Jps
10532 Launcher
11764 StringTest2
13976
E:\JVMDemo>jinfo -flag StringTableSize 11764
-XX:StringTableSize=10
4 JDK7下运行后测试默认值
E:\JVMDemo>jps
1892 Jps
13976
6984 StringTest2
4012 Launcher
E:\JVMDemo>jinfo -flag StringTableSize 6984
-XX:StringTableSize=60013
5 JDK7 下修改为 -XX:StringTableSize=1000
E:\JVMDemo>jps
13972 StringTest2
5684 Launcher
13976
3180 Jps
E:\JVMDemo>jinfo -flag StringTableSize 13972
-XX:StringTableSize=1000
6 JDK8 下修改为 -XX:StringTableSize=1000
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.
StringTable size of 1000 is invalid; must be between 1009 and 2305843009213693951
三 实战——StringTableSize性能测试
1 代码——产生10万个长度不超过10的字符串
/**
* 产生10万个长度不超过10的字符串,包含a-z,A-Z
*/
public class GenerateString {
public static void main(String[] args) throws IOException {
FileWriter fw = new FileWriter("words.txt");
for (int i = 0; i < 100000; i++) {
//1 - 10
int length = (int) (Math.random() * (10 - 1 + 1) + 1);
fw.write(getString(length) + "\n");
}
fw.close();
}
public static String getString(int length) {
String str = "";
for (int i = 0; i < length; i++) {
//65 - 90, 97-122
int num = (int) (Math.random() * (90 - 65 + 1) + 65) + (int) (Math.random() * 2) * 32;
str += (char) num;
}
return str;
}
}
2 代码——测试性能
/**
-XX:StringTableSize=1009
* 测试 StringTableSize 不同大小的性能
*/
public class StringTest2 {
public static void main(String[] args) {
BufferedReader br = null;
try {
br = new BufferedReader(new FileReader("words.txt"));
long start = System.currentTimeMillis();
String data;
while((data = br.readLine()) != null){
data.intern(); // 如果字符串常量池中没有对应 data 的字符串的话,则在常量池中生成
}
long end = System.currentTimeMillis();
System.out.println("花费的时间为:" + (end - start));
} catch (IOException e) {
e.printStackTrace();
} finally {
if(br != null){
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
3 当设置为 -XX:StringTableSize=1009
花费的时间为:259
4 当设置为 -XX:StringTableSize=100009
花费的时间为:60