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元起,快前往官网查看详情吧