java GC介绍
jvm 常用参数介绍
-Xms 初始堆大小
-Xmx 最大堆大小
-Xmn 年轻代大小
-XX:PermSize 设置持久代(perm gen)初始值
-XX:MaxPermSize 设置持久代最大值
-Xss 每个线程的堆栈大小
-XX:SurvivorRatio Eden区与Survivor区的大小比值
(并行回收gc可以使用-XX:InitialSurvivorRadio调整 并行回收这个比例不是不变的会根据程序运行动态调整)
-XX:pretenureSizeThreshold 对象超过多大是直接在旧生代分配
-XX:MaxTenuringThreshold 垃圾最大年龄
-XX:MaxGCPauseMillis: 设置大于0的毫秒数,收集器尽可能在该时间内完成垃圾回收(Parallel Scavenge专用)
-XX:CMSInitiatingOccupancyFraction =70 使用cms作为垃圾回收
使用70%后开始CMS收集
-XX:GCTimeRatio:大于0小于100的整数,即垃圾回收时间占总时间的比率,设置越小则希望垃圾回收所占时间越小,CPU能花更多的时间进行系统操作,提高吞吐量(Parallel Scavenge专用)
XX+UseCMSCompactAtFullCollection CMS是不会移动内存的,因此,这个非常容易产生碎片,导致内存不够用,因此,内存的压缩这个时候就会被启用。增加这个参数是个好习惯。这个参数是多少次fullgC进行压缩默认为零
jvm 垃圾收集器介绍
图展示了7种作用于不同分代的收集器,如果两个收集器之间有连线,说明他们可以搭配使用。
1.serial 收集器(复制算法)
该收集器历史最悠久,在jdk1.3.1之前是新生代收集的唯一选择。这是一个单线程的收集器。
缺点:由于单线程收集慢,导致stop word时间长。影响用户体验
优点:由于单线程,可以专心干事,不需要线程间的交互,在cpu核数不多的情况下是个不错的选择(目前 client模式下默认的新生代收集器)
2.ParNew 收集器(复制算法)
该收集器是Serial的多线程版本,就是采用多线程进行垃圾回收。
优点:如果是多核的服务器,多线程收集,比单线程快,stop word的时间短。
缺点:如果在cpu核数不多的情况下,性能不如serial收集器,
说明:由于jdk1.5推出了cms收集器,但由于他不能和Parallel scavenge一起工作,
只能和Serial 收集器配合使用。这样导致年轻代的收集很慢拖累整个程序,cms在这个时期使用就得不偿失了。ParNew收集器的出现让cms可以走向舞台。
3.Parallel Scavenge(复制算法,server模式下默认的收集器(附录介绍))
Parallel Scavenge 注重的是吞吐量的多线程收集器
吞吐量=运行用户代码时间/(运行用户代码时间+垃圾收集停顿时间),例:虚拟器总共
运行了100分钟,其中垃圾回收花掉1分钟,吞吐量为(99/(99+1))*100%=99%
Parallel Scavenge 可以调整两个参数
-XX:MaxGCPauseMillis收集器尽可能在该时间内完成垃圾回收,单位毫秒。
-XX:GCTimeRatio ,即垃圾回收时间占总时间的比率(0-100).
4.Serial Old(标记-整理算法)
Serial Old 是Seriall 的老年代版本,是一个单线程收集器。使用标记-整理算法(给client 模式下的虚拟机使用)。有两个用处
1.jdk1.5以及以前版本中和parallelscavenge 收集器搭配使用。
2作为CMS 收集器的后备方案,当发生ConcurrentMode Failure 时使用
5. Parallel Old 收集器(标记-整理算法)
Parallel Old 是Parallel Scavenge的老年代版本,在jdk1.6才开始提供使用的,在此之前新生代的Parallel Scavenge 一直处于比较尴尬的地位,原因是如果新生代选择了Parallel Scavenge
老年代就必须选择Serial Old,这样使用Parallel Scavenge未必能达到整体的吞吐量优先。
6.CMS(标记-清除)(以最少用户停顿时间为目标)
吞吐量优先和最少用户停顿时间优先的区别
吞吐量算法已经说过了,最少用户停顿时间是指stop word时间最短。
该收集器比其他收集器复杂一些主要有如下4步。
1.初始标记
2.并发标记
3.重新标记
4.并发清除
该收集器的优点:
并发,并发收集,用户停顿时间少。
缺点:1.对cpu敏感,在并发阶段他不会引起用户停顿,但会占用用户的一些cpu资源
默认回收线程数为(cpu数量+3/4)。
2.cms收集器无法处理浮动垃圾
浮动垃圾是指在并发处理阶段,用户线程还在运行,自然会产生垃圾,这一部分在标记之后,这次无法清理,只能等下一次清理。这部分垃圾称为浮动垃圾。
由于是和用户线程的cms垃圾回收并行运行,cms收集器不能等年老代满了才去收集,必须预留一部分空间给用户线程放对象。如果在并发收集阶段预留空间不够的话,就会发生Concurent Mode Failure 采用备用方案。(-XX:CMSInitiatingOccupancyFraction 调整预留空间大小)
3.最后一个是
由于标记清除,会有碎片产生。
7.G 1(jdk1.7 7u4 正式提供,oracle主打的收集器)
主要是以下4步
1.初始标记
2.并发标记
3.最终标记
4.筛选回收
优点
1.并发与并行
G1 可以充分利用cpu的资源,来缩短stopword 时间
2.分代收集,他不需要其他收集器配合使用,就能单独管理堆.他对新创建的对象和长期存活的对象处理方式不一样
3.空间整合整体是标记-整理,两个Region上是复制算法
4.可预测停顿,除了降低停顿还关注吞吐量。
怎样读懂GC日志
下面MInGc
package com.linkage.testgc;
//minorGC -Xms40M -Xmx40M -Xmn16M-verbose:gc -XX:+PrintGCDetails
public classMinGC {
public static void main(String[] args) throws Exception {
MemoryObjectobject = newMemoryObject(1024*1024);
MemoryObjectobject2 = newMemoryObject(1024*1024*2);
for(int i=0;i<2;i++){
happenMinorGC(9);
Thread.sleep(2000);
}
}
private staticvoidhappenMinorGC(inthappenMinorGCindex) throws Exception
{
for(inti=0;i<happenMinorGCindex;i++){
if(i==happenMinorGCindex-1){
System.out.println("minor gc should happen");
Thread.sleep(2000);
}
newMemoryObject(1024*1024);
}
}
static classMemoryObject{
private byte[]bytes;
public MemoryObject(int ObjetSize){
this.bytes= newbyte[ObjetSize];
}
}
}
[GC [PSYoungGen:16343K->1592K(18432K)] 16343K->3640K(38912K), 0.0026914 secs] [Times:user=0.00 sys=0.00, real=0.00 secs]
minor gc should happen
minor gc should happen
[GC [PSYoungGen:17617K->1624K(18432K)] 19665K->3672K(38912K), 0.0087863 secs] [Times:user=0.00 sys=0.00, real=0.01 secs]
Heap
。
下面FULL gc
package com.linkage.testgc;
import java.util.ArrayList;
import java.util.List;
//-Xms20M -Xmx20M -Xmn10M-verbose:gc -XX:+PrintGCDetails
public classFullGc {
public static void main(String[] args) throws Exception {
List<MemoryObject> objects= newArrayList<MemoryObject>();
for(int i=0;i<5;i++){
objects.add(new MemoryObject(1024*1024));
}
//让对象直接进入年老代
System.gc();
Thread.sleep(2000);
System.out.println("调用gc完毕");
objects.clear();
for(int i=0;i<10;i++){
objects.add(newMemoryObject(1024*1024));
if(i%3==0){
objects.remove(0);
}
}
Thread.sleep(5000);
}
}
[GC [PSYoungGen:5956K->600K(9216K)] 5956K->5720K(19456K), 0.0032144 secs] [Times:user=0.00 sys=0.00, real=0.00 secs]
[Full GC [PSYoungGen:600K->0K(9216K)] [ParOldGen: 5120K->5591K(10240K)]5720K->5591K(19456K) [PSPermGen: 2543K->2542K(21504K)], 0.0120996 secs][Times: user=0.05 sys=0.00, real=0.01 secs]
调用gc完毕
[Full GC [PSYoungGen:7507K->0K(9216K)] [ParOldGen: 5591K->4567K(10240K)]13098K->4567K(19456K) [PSPermGen: 2545K->2545K(21504K)], 0.0161243 secs][Times: user=0.03 sys=0.00, real=0.02 secs]
其中 Full GC 代表GC的类型 PSYoungGen代表gc的区域,7507K->0K(9216K)] 7507代表回收钱内存量0代表回收后内存量 9216K代表总内存量,其他的类似。
Times: user=0.03 sys=0.00, real=0.02 secs 代表gc的耗时
附录
.client 和server模式介绍
一.client 又称为C1 ,较为轻量级,只做少量性能开销比高的优化,占用内存较少
主要优化手段有
1.方法内联
2.去虚拟化
3.冗余消除
二.server compiler 又称为C2 较为重量级,采用了大量传统优化技术优化,占用较大内存
逃逸分析是c2优化的基础(运行状况判断变量是否会被外部读取,如果不被外部读取就是逃逸的)分为方法逃逸,线程逃逸
1.标量替换
2栈上分配
3.同步消除等