jvm垃圾收集器与内存分配策略
2019独角兽企业重金招聘Python工程师标准>>>
垃圾收集器与内存分配策略:
- 以下参考周志明的<<深入理解jvm高级特性与最佳实践>>。
判断对象是否存活:
- 引用计数:通过判断对象被引用的次数(为0,则表示不可被使用),但这很难解决对象相互循环引用的问题。
- 根搜索算法:即采用有向图的方式,判断从GC Roots到某个对象是否可达。
上图中obj1,obj2,obj3,obj4可达,obj5,obj6不可达(可被GC回收)。
- 可作为GC Roots的对象:
1. 虚拟机栈中局部变量引用的对象。
2. 类静态属性引用的对象。
3. 常量引用的对象。
4. JNI中引用的对象。
java中的引用类型:
java中有四种引用类型(由强到弱):
- 强引用(StrongReference): 只要对象有被强引用,对象就不会被GC回收,如Object o = new Object()中的o就是强引用。
- 软引用(SoftReference): 软引用的对象为不必须回收的对象,但在内存不足发生溢出之前,GC会在回收时,将软引用的对象视作可可回收的对象,所以SoftReference可以用来做一些高速缓存。
- 弱引用(WeakReference):软引用的对象只能存活到下一次GC的时候,无论内存是否足够,如WeakHashMap类。
- 虚引用(PhantomReference): 虚引用对对象存活无影响,唯一的用处,可以与ReferenceQueue结合使用,在对象被回收时,得以通知。
方法区(Permanent Generation)回收:
- java8中已经移除了Permanent Generation, 取而代之的是MetaSpace区。
- 方法区回收的对象:
1. 废弃常量(如无引用的常量字符串)。
2. 无用的类。
- 类什么条件下可以被回收:
1. 该类的所有实例已经被回收。
2. 加载该类的ClassLoader已经被回收。
3. 该类的java.lang.Class对象没有被引用,无法任何地方通过反射访问该类。
垃圾回收算法:
- 标记-清除(Mark-Sweep): 先标记要回收的对象,再统一进行回收操作。
简单方便,内存碎片化严重
- 复制算法: 将堆分为2份,1份空白(A),1份存放对象(B),GC后,将B中存活对象复制到A中,然后将B变成空白。
无内存碎片化, 浪费可用内存
- 标记-整理(Mark-Compact): 先标记可回收对象,将存活对象都移向一端,再回收对象。
无内存碎片化,充分利用可用内存
- 分代回收:将堆分为年轻代和老年代,年轻代(存活对象少)采用复制算法,老年代(对象存活长)可采用标记-清除或标记-整理。
根据对象存活特性,合理使用不同回收算法,商业JVM都使用该回收算法。
垃圾收集器:
- 既然jvm采用分代回收,那么年轻代和老年代各自使用的垃圾收集器也不一样。
- 年轻代使用的垃圾收集器:Serial,ParNew,Parallel Scavenge。
- 老年代使用的垃圾收集器:CMS, Serial Old(MSC), Parallel Old。
- 通用的垃圾收集器:G1。
Serial/Serial Old收集器:
- 单线程回收,回收期间暂停其他所有工作线程。(jvm -client模式下年轻代默认的收集器)
ParNew收集器:
- 多线程同时回收,回收期间暂停其他所有工作线程。
Parallel Scavenge收集器:
- 和ParNew类似,但其重在控制cpu吞吐量大小。
Serial Old收集器:
- Serial老年代版本。使用单线程,标记-整理的算法。
Parallel Old收集器:
- Parallel Scavenge收集器的老年代版本。使用多线程,标记-整理算法。
CMS(Concurrent Mark Sweep)收集器:
- 以获得最短回收暂停时间为目标。这是一款真正意义的并发收集器(可允许垃圾收集线程与用户线程并行)。其主要有四个阶段:
1. 初始标记:标记GC Roots可关联的对象,会暂停用户线程。
2. 并发标记:GC Roots Tracing过程,用户线程并行。
3. 重新标记:重新标记由于在并发标记过程中用户线程导致的对象状态变化,会暂停用户线程。
4. 并发清理:清理可回收对象,用户线程并行。
G1(Garbage First)收集器:
- 一款先进的垃圾收集器。它针对整个堆,将其分为大小相等的区域,记录每个区占用信息,优先回收回收价值更高的区域。
- 详解介绍:http://my.oschina.net/indestiny/blog/214160
这些收集器都一些可控参数,根据实际场景来调整,这里是官方文档:
http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html
内存分配与回收策略:
- jvm内存分配基本就是堆上分配,也有可能栈上(如通过逃逸分析,可以在栈上分配)。
- 看看整个堆分区:
对象优先分配在Eden区:
内存分配回收实例:
/*** 内存分配回收* -XX:+PrintGCDetails 打印GC信息* -Xms12M 起始堆大小* -Xmx12M 最大堆大小* -Xmn6M 年轻代大小* -XX:SurvivorRatio=6 Eden:S0:S1 = 4:1:1* * jvm args:* -XX:+PrintGCDetails -Xms12M -Xmx12M -Xmn6M -XX:SurvivorRatio=4*/
public class MemoryAllocate {private static final int _1M = 1024*1024;public static void main(String[] args) {byte[] b1 = new byte[_1M]; // allocate 1Mbyte[] b2 = new byte[_1M*2]; // allocate 2Mbyte[] b3 = new byte[_1M]; // allocate 1M, 发生年轻代GC(Minor GC)}
}
gc信息如下:
- 垃圾回收方式:
1.Minor GC:发生在年轻代,速度快,频繁。
2.Full GC/Major GC:发生在老年代, 一般也伴随Minor GC, 速度一般比Minor GC慢10倍以上。
大对象直接进入老年代:
- 可以通过设定-XX:PretenureSizeThreshold来判断当分配的对象大于这个阈值时,则直接将其分配到老年代。
- PretenureSizeThreshold只对Serial和ParNew收集器有效。
/*** PretenureSizeThreshold* -XX:+PrintGCDetails 打印GC信息* -Xms12M 起始堆大小* -Xmx12M 最大堆大小* -Xmn6M 年轻代大小* -XX:SurvivorRatio=6 Eden:S0:S1 = 4:1:1* -XX:PretenureSizeThreshold 对象超过该值,直接进入老年代,单位B* -XX:UseParNewGC 使用UserParNew收集器* jvm args:* -XX:UseParNewGC -XX:+PrintGCDetails -Xms12M -Xmx12M -Xmn6M -XX:SurvivorRatio=4 -XX:PretenureSizeThreshold=2097152*/
public class PretenureSizeThreshold {private static final int _1M = 1024*1024;public static void main(String[] args) {// 分配2M, 大于PretenureSizeThreshold, 直接进入老年代byte[] b1 = new byte[_1M * 3]; }
}
其他参数介绍:
- MaxTenuringThreshold: 在Eden区,对象在每次Minor GC后存活下来,则其年龄+1, 当存活对象年龄大于MaxTenuringThreshold时,就进入老年代。
- HandlePromotionFailure: 空间担保机制。在发生Minor GC时,虚拟机会检测比较每次晋升到老年代的平均大小与老年代剩下的空间大小,如果大于,则进行一次Full GC;如果小于,则查看HandlePromotionFailure是否允许担保失败,若允许只进行Minor GC;若不允许,还是会进行一次Full GC。
上面就基本介绍了jvm分配回收内存策略。
不吝指正。
转载于:https://my.oschina.net/indestiny/blog/214276
jvm垃圾收集器与内存分配策略相关推荐
- JVM:垃圾收集器与内存分配策略
垃圾收集器与内存分配策略 1.对象已死吗 1).引用计数算法 引用计数算法:给对象中添加一个引用计数器,每当有一个地方引用它时,计数器值就加1:当引用失效时,计数器值就减1:任何时刻计数器为0的对象就 ...
- java eden分配参数,JVM垃圾收集器与内存分配策略,
垃圾收集器与内存分配策略 对象存活判断 引用计数算法 给对象添加一个计数器,每有一个引用+1,当引用失效-1,若为0则不在被使用. 可达性分析算法 对象是否可到达GC roots 或者说GC root ...
- JVM垃圾收集器与内存分配策略学习总结
方法区: 1.线程共享 2.储存类信息,常量,静态变量,编译器编译后的代码 3.非堆(别名)用于区分Java堆 4.不需要连续的内存 5.可以固定或可扩张 6.选择不实现垃圾回收//这个区域很少进行垃 ...
- [JVM] 垃圾收集器与内存分配策略
目录 简介 哪些内存需要回收 引用计数算法 可达性分析 再次谈引用 生存和死亡 简介 GC(Carbage Coolection),需要完成的3件事情 : 哪些内存需要回收 什么时候回收 如何回收 程 ...
- jvm(3)-垃圾收集器与内存分配策略
[0]README 0.1)本文部分文字转自:深入理解jvm,旨在学习 垃圾收集器与内存分配策略 的基础知识: [1]垃圾回收概述 1)GC(Garbage Collection)需要完成的3件事情: ...
- 垃圾收集器与内存分配策略(五)之垃圾日志与常见参数
2019独角兽企业重金招聘Python工程师标准>>> 垃圾收集器与内存分配策略(五)--垃圾日志与常见参数 理解GC日志 每个收集器的日志格式都可以不一样,但各个每个收集器的日志都 ...
- 【深入理解Java虚拟机学习笔记】第三章 垃圾收集器与内存分配策略
最近想好好复习一下java虚拟机,我想通过深读 [理解Java虚拟机 jvm 高级特性与最佳实践] (作者 周志明) 并且通过写一些博客总结来将该书读薄读透,这里文章内容仅仅是个人阅读后简短总结,加强 ...
- java_opts gc回收器_jvm垃圾收集器与内存分配策略
垃圾收集器与内存分配策略: 以下参考周志明的<>. 判断对象是否存活: 引用计数:通过判断对象被引用的次数(为0,则表示不可被使用),但这很难解决对象相互循环引用的问题. 根搜索算法:即采 ...
- 7种垃圾收集器与内存分配策略,看这一篇就够了
垃圾收集器与内存分配策略-垃圾收集器 (A).图中展示了7种不同分代的收集器: Serial.ParNew.Parallel Scavenge.Serial Old.Parallel Old.CMS. ...
最新文章
- iOS三种拨打电话的方法
- JavaScript 利用location对象实现跨页面传参
- ToString 的几个思考
- python调用电脑蜂鸣器一直响_电脑开机蜂鸣器一直响,9声滴~,什么问题?怎么处理?...
- 动态改变stage桢数
- 数字货币交易所数据安全随笔
- win7 64位 安装oiracle 32位 plsql问题
- 兄弟打印机内存已满清零方法_兄弟打印机清零大全
- 爬虫学习——大碗宽面b站和网易云可视化分析代码
- matplotlib pyqt4
- cogs 448. 神牛果 神奇好理解的思路
- jupyter和spider;Anaconda、Python、Jupyter、Pycharm、Spyder、conda、pip
- OS + Unix FreeBSD / MacOSX Snow Leopard 10.6.3-8 / MacBook Pro / apple / MC373
- Java使用google开源工具Thumbnailator实现图片压缩
- android通过ip查询地址吗,Android 根据IP地址获取城市
- 用Java实现二叉堆、大顶堆和小顶堆
- cornerstone出现 Unable to connect to a repository at URL
- 图像仿射变换shear怎么翻译?剪切、错切、推移哪个译词好?
- python汉语分词_使用python进行汉语分词-乾颐堂
- [附源码]计算机毕业设计财务管理系统Springboot程序