深入理解java虚拟机(七):java垃圾收集分析总结
深入理解java虚拟机(一):java内存区域(内存结构划分)深入理解java虚拟机(二):java内存溢出实战 深入理解java虚拟机(三):String.intern()-字符串常量池深入理解java虚拟机(四):对象存活判定算法和垃圾收集算法深入理解java虚拟机(五):hotspot垃圾收集算法实现 深入理解java虚拟机(六):java垃圾收集分析
深入理解java虚拟机(一):java内存区域(内存结构划分)
深入理解java虚拟机(二):java内存溢出实战
深入理解java虚拟机(三):String.intern()-字符串常量池
深入理解java虚拟机(四):对象存活判定算法和垃圾收集算法
深入理解java虚拟机(五):hotspot垃圾收集算法实现
深入理解java虚拟机(六):java垃圾收集分析实战(内存分配与回收策略)
深入理解java虚拟机(八):java内存分析工具-MAT和OQL
一、垃圾回收触发条件
1、Minor gc触发条件
当新生代空间不足时会主动触发Minor gc,并且自动扩容(可通过控制使新生代直接处于最大内存空间,避免自动扩容和垃圾收集)。
2、Full gc触发条件
和新生代一样,当老年代空间不足时会触发Full gc,并且自动扩容;另外当在代码中调用System.gc()时也会触发Full gc。 可通过参数-XX:+DisableExplicitGC 控制使System.gc()失效。
3、永久待触发条件
类似上面,当永久待空间不足时,会发出Full gc,可通过控制PermSize=MaxPermSize 避免自动扩容和垃圾回收。另外可通过参数-Xnoclassgc 来控制虚拟机不对类(永久待类对象)进行回收。
二、Runtime.exec创建新进程(内存叠加)占用外部内存
java虚拟机执行Runtime.exec 的过程是:首先克隆一个和当前虚拟机拥有一样环境变量的进程,再用这个心的进程区执行外部命令,最后再退出这个进程。
如果频繁执行,系统的消耗会很大,不仅是cpu还有内存。
另外这个时候要注意了,在采集java程序的内存时,一定要注意有java程序通过Runtime.exec创建的新进程所占用的内存,按理来说,java创建的新进程所占用的内存也应该归属于这个java程序的内存。
例:下面是在redhat下面用java程序通过Runtime.exec执行shell脚本。
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Date;
public class TestSleep {
public static void main(String[] args) {
System.out.println("being sleep"+new Date().toLocaleString());
try
{
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("/home/boco/script/sleep.sh");
InputStream stdin = proc.getInputStream();
InputStreamReader isr = new InputStreamReader(stdin);
BufferedReader br = new BufferedReader(isr);
String line = null;
System.out.println("output");
while ( (line = br.readLine()) != null)
System.out.println(line);
System.out.println("");
int exitVal = proc.waitFor();
System.out.println("Process exitValue: " + exitVal);
} catch (Throwable t)
{
t.printStackTrace();
}
System.out.println("end sleep"+new Date().toLocaleString());
}
}
shell脚本内容:
#!/bin/bash
echo "begin"
sleep 10
echo "end"
执行结果:
可以看出有java进程产生了一个子进程,即shell脚本,而这个shell脚本又产生了一个子进程,即sleep。
三、类加载-字节码验证时间
类加载时间即虚拟机加载类所耗掉的总时间。
字节码验证会耗掉一部分时间,在保证字节码是安全的情况下,可以通过参数 -Xverify:none禁止掉字节码验证过程。
四、编译时间
编译时间:指虚拟机的JIT编译器(Just in time Compiler)编译热点代码(Hot Spot Code)的耗时。
我们知道java语言为了实现跨平台的特性, java代码编译出来后形成的class文件中存储的是字节码(ByteCode),虚拟机通过解释方式执行字节码命令,比起c语言的编译执行速度要慢不少。 不过在java1.2后,虚拟机内置了2个运行期间编译器(代号为C1和C2,C1在client模式下启用,C2在server模式下启用),如果一个java方法被调用数次到一定程度就会被判定为热代码交个JIT编译器编译为本地代码, 提高运行速度,这就是hotspot虚拟机名字的由来。
编译时间总长即为编译热代码所消耗的时间总和。
五、垃圾收集打印参数
-XX:+PrintGCApplicationStoppedTime 参数打印gc停顿时间
-XX:+PrintGCDateStamps 参数打印gc时间戳,系统时间
-XX:+PrintGCTimeStamps 参数打印gc时间,相对于jvm启动时间
-Xloggc:gclog.log 设置gc日志文件
-XX:+PrintReferenceGC 打印gc引用
-XX:+PrintGCApplicationConcurrentTime 打印每次垃圾回收前,程序未中断的执行时间
-XX:+PrintHeapAtGC 打印GC前后的详细堆栈信息
例:
-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCDateStamps -Xloggc:gclog.log -XX:+PrintGCApplicationConcurrentTime -XX:+PrintHeapAtGC
输出gclog.log:
Application time: 0.0055586 seconds
{Heap before GC invocations=0 (full 0):
def new generation total 9216K, used 6487K [0x32750000, 0x33150000, 0x33150000)
eden space 8192K, 79% used [0x32750000, 0x32da5fd0, 0x32f50000)
from space 1024K, 0% used [0x32f50000, 0x32f50000, 0x33050000)
to space 1024K, 0% used [0x33050000, 0x33050000, 0x33150000)
tenured generation total 10240K, used 0K [0x33150000, 0x33b50000, 0x33b50000)
the space 10240K, 0% used [0x33150000, 0x33150000, 0x33150200, 0x33b50000)
compacting perm gen total 12288K, used 377K [0x33b50000, 0x34750000, 0x37b50000)
the space 12288K, 3% used [0x33b50000, 0x33bae748, 0x33bae800, 0x34750000)
ro space 10240K, 55% used [0x37b50000, 0x380d1140, 0x380d1200, 0x38550000)
rw space 12288K, 55% used [0x38550000, 0x38bf44c8, 0x38bf4600, 0x39150000)
2014-02-26T15:44:05.625+0800: 0.049: [GC 0.049: [DefNew: 6487K->151K(9216K), 0.0040768 secs] 6487K->6295K(19456K), 0.0041381 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Heap after GC invocations=1 (full 0):
def new generation total 9216K, used 151K [0x32750000, 0x33150000, 0x33150000)
eden space 8192K, 0% used [0x32750000, 0x32750000, 0x32f50000)
from space 1024K, 14% used [0x33050000, 0x33075ee8, 0x33150000)
to space 1024K, 0% used [0x32f50000, 0x32f50000, 0x33050000)
tenured generation total 10240K, used 6144K [0x33150000, 0x33b50000, 0x33b50000)
the space 10240K, 60% used [0x33150000, 0x33750030, 0x33750200, 0x33b50000)
compacting perm gen total 12288K, used 377K [0x33b50000, 0x34750000, 0x37b50000)
the space 12288K, 3% used [0x33b50000, 0x33bae748, 0x33bae800, 0x34750000)
ro space 10240K, 55% used [0x37b50000, 0x380d1140, 0x380d1200, 0x38550000)
rw space 12288K, 55% used [0x38550000, 0x38bf44c8, 0x38bf4600, 0x39150000)
}
Total time for which application threads were stopped: 0.0043639 seconds
Heap
def new generation total 9216K, used 4575K [0x32750000, 0x33150000, 0x33150000)
eden space 8192K, 54% used [0x32750000, 0x32ba1fa8, 0x32f50000)
from space 1024K, 14% used [0x33050000, 0x33075ee8, 0x33150000)
to space 1024K, 0% used [0x32f50000, 0x32f50000, 0x33050000)
tenured generation total 10240K, used 6144K [0x33150000, 0x33b50000, 0x33b50000)
the space 10240K, 60% used [0x33150000, 0x33750030, 0x33750200, 0x33b50000)
compacting perm gen total 12288K, used 377K [0x33b50000, 0x34750000, 0x37b50000)
the space 12288K, 3% used [0x33b50000, 0x33bae748, 0x33bae800, 0x34750000)
ro space 10240K, 55% used [0x37b50000, 0x380d1140, 0x380d1200, 0x38550000)
rw space 12288K, 55% used [0x38550000, 0x38bf44c8, 0x38bf4600, 0x39150000)
Application time: 0.0007510 seconds
更多推荐
所有评论(0)