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
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