举一个简单java调优例子,一个大对象导致full GC的例子
下面是一个产生大对象,MinorGC的时候总有很多的大对象没有被回收,需要将这些对象放入到年老带中,导致年老带使用量增长过快引发full GC。
class T33 extends Thread {
public void run() {
List<Map<String,String>> list = new ArrayList();
for(int i=0;i<99999999;i++){
Map<String,String> map = new HashMap<String,String>(5000);
map.put("aaa", "123");
list.add(map);
try {
if(list.size()==5000){
//Thread.sleep(300000);
list =new ArrayList();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(map);
}
}
}
class Test2 {
public static void main(String[] args) throws InterruptedException {
T33 t4 = new T33();
t4.start();
}
}
首先使用jps -l 或者 ps ef|grep java 查到进程,我这里使用的是 jps -l。
找到了进程12829。
再用jstat -gc 查看垃圾回收
输入jstat -gc 12829 300 20 ;这个命令的意思是打印12829垃圾回收过程20次,每300毫秒打印一次。
可以看到进程12829的Full GC还是很频繁的饿,这是由于Minor GC的时候剩余的对象太多,surviceor区域放不下后只好放到年老带,导致年老带增加的对象特别快。
再用jmap -histo:live 12829
可以看到HashMap的Node对象所占内存特别多,基本可以认定是产生了比较大的HahMap导致的Full GC过快的。
我们还可以dump产生进程的快照文件,对着文件分析一下。
使用命令 jmap -dump:format=b,file=tiaoyoutest.txt 12829,其中tiaoyoutest.txt就是所产生的文件
再使用Jhat -J-Xmx512m 7000 tiaoyoutest.txt 。其中Xmx是制定启动的内存大小,7000是启动的端口号。输入这个后我们就可以在浏览器中输入:127.0.0.1:7000看到对堆文件的分析了,但是感觉没有什么用。要用专业的工具,比如Meta。
我这里是在mac上操作的,它不需要我输入端口号,如果输入端口号还有问题
再到浏览器里输入127.0.0.1:7000