GC算法分析

25 篇文章 0 订阅
6 篇文章 0 订阅

GC

频繁收集Young区,较少收集Old区,基本不动Perm区

jdk1.7

新生代:-Xmn

新生代+旧生代:-Xms -Xmx

永久代:-XX:PermSize,-XX:MaxPermSize

jdk1.8

jdk1.8之后将最初的永久代取消,由元空间取代

目的:将HotSpot与Rockit两个虚拟机的标准整合

堆内存调优

  • -Xms
    • 设置初始内存大小,默认为物理内存的1/64
  • -Xmx
    • 最大分配内存,默认为物理内存的1/4
  • -XX:+PrintGCDetails
    • 输出详细的GC处理日志
package top.ygy.jvm;

/**
 * @Description: TODO(这里用一句话描述这个类的作用)
 * @author yangguangyuan
 * @date 2019年6月27日 -Xmx1024m -Xms1024m -XX:+PrintGCDetails
 */
public class StackDemo2 {
	public static void main(String[] args) {
		long maxMemory = Runtime.getRuntime().maxMemory();// java虚拟机(这个进程)能构从操作系统那里挖到的最大的内存
		long totalMemory = Runtime.getRuntime().totalMemory();// java虚拟机这个进程当时所占用的所有内存

		System.out.println("maxMemory=" + maxMemory + "字节 "
				+ maxMemory / (double) 1024 / 1024 + "MB");
		System.out.println("totalMemory=" + totalMemory + "字节 "
				+ totalMemory / (double) 1024 / 1024 + "MB");
	}
}

自动触发垃圾回收

若养老区执行了Full GC后发现依然无法进行对象的保存,就回产生OOM异常,

package top.ygy.jvm;

import java.util.Random;

/**
 * @Description: TODO(这里用一句话描述这个类的作用)
 * @author yangguangyuan
 * @date 2019年6月27日 
 * -Xmx1m -Xms1m -XX:+PrintGCDetails
 */
public class StackDemo3 {
	public static void main(String[] args) {
		String str = "ceshiceshiceshiceshiceshi";
		while(true) {
			str = str+new Random().nextInt(8888888)+new Random().nextInt(9999999);
		}
	}
}

结果:

[Full GC (Ergonomics) [PSYoungGen: 364K->361K(1024K)] [ParOldGen: 492K->492K(512K)] 857K->853K(1536K), [Metaspace: 2834K->2834K(1056768K)], 0.0045862 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Allocation Failure) [PSYoungGen: 361K->361K(1024K)] [ParOldGen: 492K->492K(512K)] 853K->853K(1536K), [Metaspace: 2834K->2834K(1056768K)], 0.0048538 secs] [Times: user=0.02 sys=0.00, real=0.00 secs] 
Exception in thread "main" Heap
 PSYoungGen      total 1024K, used 379K [0x00000000ffe80000, 0x0000000100000000, 0x0000000100000000)
  eden space 512K, 74% used [0x00000000ffe80000,0x00000000ffededc8,0x00000000fff00000)
  from space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
  to   space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
 ParOldGen       total 512K, used 492K [0x00000000ffe00000, 0x00000000ffe80000, 0x00000000ffe80000)
  object space 512K, 96% used [0x00000000ffe00000,0x00000000ffe7b308,0x00000000ffe80000)
 Metaspace       used 2866K, capacity 4486K, committed 4864K, reserved 1056768K
  class space    used 304K, capacity 386K, committed 512K, reserved 1048576K
java.lang.OutOfMemoryError: Java heap space

GC三大算法

​ JVM在进行GC时,并非每次都对三个内存区域一起回收,大部分回收的都是指新生代,因此GC按照回收的区域又分为两种类型,一种是普通GC(minor GC),一种是全局GC(major GC or Full GC).

  • 普通GC:只针对新生代区域GC
  • 全局GC:针对旧生代GC,偶尔伴随对新生代的GC以及对永久代的GC

复制算法

优势劣势

  • 优点
    • 不会产生内存碎片,完整度极高
  • 缺点
    • 浪费一半空间,总要有50%是to区域
    • 如果对象存活率很高,花费时间多,所以需要对象存活率很低,而且必须克服50%的内存浪费

使用场景

Minor GC(普通GC)

  • 年轻代中使用的是minor GC,这种GC算法采用的是复制算法(Copying)

组成部分

​ 我们首先一起来看一下复制算法的做法,复制算法将内存划分为两个区间,在任意时间点,所有动态分配的对象都只能分配在其中一个区间(称为活动区间),而另外一个区间(称为空闲区间)则是空闲的

​ 当有效内存空间耗尽时,JVM将暂停程序运行,开启复制算法GC线程。接下来GC线程会将活动区间内的存活对象,全部复制到空闲区间,且严格按照内存地址依次排列,与此同时,GC线程将更新存活对象的内存引用地址指向新的内存地址

​ 此时,空闲区间已经与活动区间交换,而垃圾对象现在已经全部留在了原来的活动区间,也就是现在的空闲区间。事实上,在活动区间转换为空间区间的同时,垃圾对象已经被一次性全部回收。

标记清除

优势劣势

  • 优点
    • 不需要额外空间
  • 缺点
    • 两次扫描,耗时严重
    • 会产生内存碎片

使用场景

​ 旧生代一般是由标记清除或者标记清除与标记整理的混合实现

组成部分

​ Mark-Sweep,Full GC,标记清除是标记死的

  1. 标记:从根集合开始扫描,对存活的对象进行标记
  2. 清除:扫描整个内存空间,回收未被标记的对象,使用free-list记录可以区域

标记整理

优势劣势

  • 优点
    • 不会产生内存碎片
  • 缺点
    • 效率不高,不仅要标记存活的对象,还要整理所有存活对象的引用地址
    • 从效率上说,标记整理算法要低于复制算法

使用场景

​ 旧生代一般是由标记清除或者标记清除与标记整理的混合实现

组成部分

​ Mark-Compact,Full GC,标记整理是标记活的

相似对比

  • 内存效率:复制算法>标记清除算法>标记整理算法(简单的时间复杂度对比)
  • 内存整齐度:复制算法=标记整理算法>标记清除算法
  • 内存利用率:标记整理算法=标记清除算法>复制算法
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值