JVM学习笔记——内存结构篇( 八 )

StringTable常见面试题解答下面我们给出一个StringTable的常见面试题来进行测试:
package cn.itcast.jvm.t1.stringtable;/** * 演示字符串相关面试题 */public class Demo1_21 {// 我们会给出StringTable和堆的值public static void main(String[] args) {// StringTable=["a"]String s1 = "a";// StringTable=["a","b"]String s2 = "b";// StringTable=["a","b","ab"]String s3 = "a" + "b"; // ab// StringTable=["a","b","ab"],堆:"ab"String s4 = s1 + s2;// new String("ab") 和 s3 不相等// StringTable=["a","b","ab"],堆:"ab"String s5 = "ab"; // s3 == s5// StringTable=["a","b","ab"],堆:"ab"String s6 = s4.intern(); // s4是堆里的ab,s6是StringTable里面的ab// 问System.out.println(s3 == s4); // falseSystem.out.println(s3 == s5); // trueSystem.out.println(s3 == s6); // true// StringTable=["a","b","ab","c","d"],堆:"ab"."c","d","cd"String x2 = new String("c") + new String("d"); // new String("cd")// StringTable=["a","b","ab","c","d","cd-来自堆"],堆:"ab"."c","d","cd"x2.intern();// x1是StringTable里面的cd,但StringTable里面的cd来自堆,所以x1 == x2String x1 = "cd";System.out.println(x1 == x2);// 问,如果调换了【最后两行代码】的位置呢,如果是jdk1.6呢(这个就自己思考啦~)}}StringTable垃圾回收问题StringTable会自动进行垃圾回收,这也是我们在JDK运行中选择StringTable的原因之一
我们通过一个简单的案例进行解释:
package cn.itcast.jvm.t1.stringtable;import java.util.ArrayList;import java.util.List;/** * 演示 StringTable 垃圾回收 * -Xmx10m -XX:+PrintStringTableStatistics(打印StringTable内容) -XX:+PrintGCDetails -verbose:gc(打印垃圾回收) */public class Demo1_7 {public static void main(String[] args) throws InterruptedException {int i = 0;try {for (int j = 0; j < 100000; j++) { // 设置1w个数// 这里如果不采用.intern()// 我们会发现1w个数全部存入内存中String.valueOf(j);i++;}} catch (Throwable e) {e.printStackTrace();} finally {System.out.println(i);}}}/** * 演示 StringTable 垃圾回收 * -Xmx10m -XX:+PrintStringTableStatistics(打印StringTable内容) -XX:+PrintGCDetails -verbose:gc(打印垃圾回收) */public class Demo1_7 {public static void main(String[] args) throws InterruptedException {int i = 0;try {for (int j = 0; j < 100000; j++) { // 设置1w个数// 这里如果采用.intern()// 我们会发现StringTable里面的值会少于1w,这是因为发生了垃圾回收,回收掉不使用的信息String.valueOf(j).intern();i++;}} catch (Throwable e) {e.printStackTrace();} finally {System.out.println(i);}}}StringTable调优最后我们介绍StringTable的调优方法:

  1. 设置桶的个数
// 我们直到StringTable是一个哈希表,哈希表里面桶的个数会影响其效率// 如果桶过少,每个桶存储信息过多导致查找缓慢;如果桶过多,导致信息分布较为疏散导致查找缓慢// 我们提供一个配置来改变桶的个数:-XX:StringTableSize=10000(需要设计恰到好处的桶个数)package cn.itcast.jvm.t1.stringtable;import java.io.BufferedReader;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStreamReader;/** * 演示串池大小对性能的影响 * -Xms500m -Xmx500m -XX:+PrintStringTableStatistics -XX:StringTableSize=1009 */public class Demo1_24 {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);}}}
  1. 考虑字符串对象是否入池
// 我们同样可以采用intern来判断该字符串是否应该入池// 我们排除掉相同的字符串自然可以节省空间~package cn.itcast.jvm.t1.stringtable;import java.io.BufferedReader;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStreamReader;import java.util.ArrayList;import java.util.List;/** * 演示 intern 减少内存占用 * -XX:StringTableSize=200000 -XX:+PrintStringTableStatistics * -Xsx500m -Xmx500m -XX:+PrintStringTableStatistics -XX:StringTableSize=200000 */public class Demo1_25 {public static void main(String[] args) throws IOException {List<String> address = new ArrayList<>();System.in.read();for (int i = 0; i < 10; i++) {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;}// 如果这里不采用.tern会导致全部字符串进入,导致储存较多address.add(line);}System.out.println("cost:" +(System.nanoTime()-start)/1000000);}}System.in.read();}}/** * 演示 intern 减少内存占用 * -XX:StringTableSize=200000 -XX:+PrintStringTableStatistics * -Xsx500m -Xmx500m -XX:+PrintStringTableStatistics -XX:StringTableSize=200000 */public class Demo1_25 {public static void main(String[] args) throws IOException {List<String> address = new ArrayList<>();System.in.read();for (int i = 0; i < 10; i++) {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;}// 如果这里采用.tern就会筛选字符串,来进行调优~address.add(line.tern());}System.out.println("cost:" +(System.nanoTime()-start)/1000000);}}System.in.read();}}

经验总结扩展阅读