JVM调优之StringTable调优-创新互联

jdk1.8之后,JVM内存结构如下

创新互联公司致力于网站制作、网站建设,成都网站设计,集团网站建设等服务标准化,推过标准化降低中小企业的建站的成本,并持续提升建站的定制化服务水平进行质量交付,让企业网站从市场竞争中脱颖而出。 选择创新互联公司,就选择了安全、稳定、美观的网站建设服务!

所谓的StringTable,即字符串常量池(以下简称串池),存放在堆内存中。

我们先介绍一下intern方法

String s = "ab";
//将这个字符串对象尝试放入串池,如果有则并不会放入,如果没有则放入串池,会把串池中的对象返回
String s2 = s.intern();

调优方法1.因为StringTable是由HashTable实现的,所以可以适当增加HashTable桶的个数,来减少字符串放入串池所需要的时间。

示例代码:遍历文本文件,读取每一行的内容放入串池

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);
        }


    }
}

linux.words是存放文本的文件(实际文本有四百多万行,只粘贴部分做示例)

1080
10-point
10th
11-point
12-point
16-point
18-point
1st
2
20-point
2,4,5-t
2,4-d
2D
2nd
30-30
3-D
3-d
3D
3M
3rd
48-point
4-D
4GL
4H
4th
5-point
5-T
5th
6-point
6th
7-point
7th
8-point
8th
9-point
9th
-a
A
A.
a
a'
a-
a.
A-1
A1
a1
A4
A5
AA
aa

我们运行程序,发现耗时不到1s

然后我们设置JVM运行参数,修改桶的数量为1009,再次运行

-XX:+PrintStringTableStatistics -XX:StringTableSize=1009

运行结果耗时8秒 如下图

StringTable默认的桶的数量是60013,当桶的数量设置变小,哈希碰撞的概率增加,链表长度

变长,数据插入就会变慢,可以适当增加HashTable桶的个数,来减少字符串放入串池所需要的时间。

调优方法2:如果应用里有大量的字符串,而且字符串可能存在重复的问题,可以通过intern方法让字符串入池,减少字符串个数(触发垃圾回收 没入池的字符串被回收掉),节约堆内存的使用

示例代码:同样是遍历上述的文本文件,将每一行的内容放入ArrayList中,循环操作10次

public class Demo1_25 {
    public static void main(String[] args) throws IOException {
        Listaddress = 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;
                    }
                    address.add(line);
                }
                System.out.println("cost:" +(System.nanoTime()-start)/1000000);
            }
        }
        System.in.read();
    }
}

运行以上代码,我们控制台输入

jvisualvm 

查看字符串所占用的内存使用情况 

然后我们敲下Enter执行我们的主程序,遍历文本文件,发现内存占用飙高很多

然后我们修改代码(只改了一行代码,address.add(line.intern())

public class Demo1_25 {
    public static void main(String[] args) throws IOException {
        Listaddress = 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;
                    }
                     //仅修改这一处代码
                    address.add(line.intern());
                }
                System.out.println("cost:" +(System.nanoTime()-start)/1000000);
            }
        }
        System.in.read();
    }
}

再运行查看内存占用情况,下降了很多

我们循环遍历10次,会在堆中产生很多重复的字符串,而ArrayList中存放的对象都来自串池,堆中的字符串 如果没被引用,会被垃圾回收掉,从而节约了堆内存的使用

你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧


文章标题:JVM调优之StringTable调优-创新互联
文章链接:http://scyanting.com/article/dpdejo.html