Overview and tuning of StringTable in JVM

StringTable in JVM

Three, characteristics

  • A string in a constant pool is a symbol only, it becomes an object when it is first used
  • Using the mechanism of string pool to avoid creating string objects repeatedly
  • The principle of string variable splicing is StringBuilder (1.8)
  • The principle of string constant splicing is compiler optimization
  • You can use the inter method to actively put string objects that are not in the string pool into the string pool

2, JVM compile time optimization

  • StringTable is a hashtable structure and cannot be expanded

  • public static void main(String[] args) {
    	String s1 = "a";
    	String s2 = "b";
    	String s3 = "ab";
        //new StringBuilder().append("a").append("b").toString() new String("ab")
    	String s4 = s1 + s2;
    	String s5 = "a" + "b";
    }
    
  • ldc #2 will change the a symbol to the "a" string object
    ldc #3 changes the b symbol to a "b" string object
    ldc #4 will change the AB symbol to an "ab" string object
    
  • When String s4 = s1 + s2; is executed, it is equivalent to executing new String("ab")

  • When executing String s5 = "a" + "b", the compiler will automatically optimize, the same as String s3 = "ab"; the same

3, String delay loading

  • The jvm creates objects only when it executes to the row created by string
  • The same string created will not be created repeatedly
        String s1 = "1";//String object: 3153
        String s2 = "2";
        String s3 = "3";
        String s4 = "4";
        String s5 = "5";
        String s6 = "6";

        String s11 = "1";//String object: 3159
        String s21 = "2";
        String s31 = "3";
        String s41 = "4";
        String s51 = "5";
        String s61 = "6";//String object: 3159

4, intern()

  • Function: attempts to put the specified string into StringTable

  • Syntax: String object. intern()

  • Example:

//Create a string object in the heap
String s = new String("a") + new String("b");
//Try to put the value in this string object into StringTable, and return the object in the string pool,
String s1 = s.intern();
System.out.println(s1 == "ab"); // true
System.out.println(s == "ab"); // true

Note: when there is no string that intern tries to put into the string pool, the string will be put into the string pool, and s will become an object in the string pool

In 1.6, a copy of s will be copied into the string pool, and the position of s will not be changed

//Add "ab" to the string pool
String x = "ab";
//Create a string object in the heap
String s = new String("a") + new String("b");
//Try to put the value in this string object into StringTable, and return the object in the string pool (not put successfully)
System.out.println(s1 == x); // true
System.out.println(s == x); // false

Note: when there is a string that intern tries to put into the string pool, the string will not be put into the string pool. At this time, s is still an object in the heap, so s is not equal to x

5, StringTable tuning

  • Use the - XX:StringTableSize = size parameter to increase the number of buckets to increase StringTable performance
  • Actual use:
    public static void main(String[] args) {
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(new File("f:\\test.txt"))));
            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);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

  • By reading the file, each line in the file is added to the StringTable line by line, and the bucket size is modified to test the required time (8145 lines in the file)
StringTableSize Time
128 172 ms
1024 116 ms
4096 87 ms

Into the pool to remove weight and optimize performance

  • Source code
    public static void main(String[] args) {
        try {
            List<String> list = new ArrayList<>();
            System.in.read();
            for (int i = 0; i < 30; i++) {
                BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(new File("f:\\test.txt"))));
                String line = null;
                long start = System.nanoTime();
                while (true) {
                    line = reader.readLine();
                    if (line == null) {
                        break;
                    }
                    //No pool
                    list.add(line);
                    //Entering pool
                    //list.add(line.intern());
                }
                System.out.println("cost:" + (System.nanoTime() - start) / 1000000);
            }
            System.in.read();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
  • No pool

  • Entering pool

string object size reduced from 6m to 500k, byte array from 16m to 1m

106 original articles published, 45 praised, 30000 visitors+
Private letter follow

Tags: jvm

Posted on Wed, 05 Feb 2020 06:39:28 -0500 by upit