Android 精进:简述 JVM 基础(三):垃圾收集器与内存分配策略
来源:互联网 发布:阿甘 java 编辑:程序博客网 时间:2024/05/18 06:41
作者 | 井方哥
地址 | https://zhuanlan.zhihu.com/p/30618681
声明 | 本文是 井方哥 原创,已获授权发布,未经原作者允许请勿转载
前言
了解了 JVM 中的内存分配以及数据存储的情况,那么怎么分配的方式是最高效的,对于已经过期无用的内存占用我们怎么回收起来,这个活必须得有人来干。好在JVM自带有垃圾回收机制,我们不需要关心这些,但是当我们需要排除各种内存溢出,内存泄漏的问题时。了解其中的一些知识还是很有必要的。
说明: 本系列多处摘抄《深入理解Java虚拟机》中内容,主要精简了本书的要点,并叙述自己对本书的理解。本人才疏学浅,文章中有不对的地方,还望批评指教。
对象
1、引用计数算法
定义:给对象添加一个引用计数器,当增加一个引用时,加1,当一个引用时,减1;
缺陷:当对象之间互相循环引用时,就会变的像“不死对象”;
2、可达性分析算法
定义:从“GC Roots”为起点,向下搜索引用链,当一个对象的引用没有和引用链有任何的连接的时候,可以判定为可以回收的对象;
分类:
虚拟机栈中(栈中本地变量表)引用的对象;
本地方法栈中JNI引用的对象;
方法区中静态属性的对象;
方法区中常量引用的对象;
3、引用
强引用:“=”实现,引用只要还在,就不会被GC回收;
软引用:SoftReference实现,在内存不足发生OOM之期,就回收掉该引用;
弱引用:WeakReference实现,在下一次GC前,就回收掉该引用;
虚引用:PhantomReference实现,在任何时候可能被回收,不过回收后可以收到系统的通知;
4、finalize方法自救
如果GC Roots 不可达,进行第一次标记;
再看finalize()方法有没有被复写,有则先执行finalize()方法;
逃命方法:将自己关联到类变量之类或者某对象的成员变量的;
终身只有一次调用机会;
接着GC进行第二次标记,如果没有逃脱,则回收;
5、无用的类
所有该类的实例已被回收
该类的ClassLoad已被回收
该类对应的java.lang.Class没有在任何地方被引用,不存在该类的反射
垃圾回收算法
1、标记——清除法
方案:先标记,然后直接回收
缺陷:产生大量碎片,不好分配大内存
2、复制算法
方案:将内存分为AB两块,回收时,将A块的对象全部复制到B,然后把未回收的上移,然后把已使用过的A全部清除;
优点:实现简单,运行高效;
缺陷:有一半处于无用状态,浪费;
HotSpot:通过 Eden:Surivor:Surivor=8:1:1的比例分配,这样只有10%的空间浪费;不足时,需要依赖其他内存分配担保;
3、标记—整理算法
方案:标记—清理之后,再整体上移;
适应:适合老年代内存区使用
4、分代收集算法
新生代:使用复制算法
老年代:使用“标记-清理”或者“标记—整理”算法
垃圾收集器
1、 Serial收集器
这个收集器是一个单线程收集器,
只会使用一个CPU或者一条收集线程进行垃圾收集工作
其余的工作现场必须暂停,直到收集结束
2、ParNew收集器
Serial收集器的多线程版本
垃圾收集器线程和工作线程同时工作
3、Paraller Scavenge收集器
目标:达到一个可控的吞吐量
吞吐量: 用户运行时间/(用户运行时间+垃圾回收时间)
GC自适应调节:调整参数提供最合适的停顿时间或者最大的吞吐量
4、CMS收集器
目标:最短回收停顿时间
步骤:
初始标记
并发标记
重新标记
并发清除
缺点:
对CPU资源非常敏感
无法处理浮动垃圾
基于“标记-清除”算法实现,碎片多
5、G1 收集器
并行与并发
分代收集
空间整合:
整体看:基于“标记-整理”算法
局部看:基于“复制”算法
可预测停顿
有计划避免 Java 堆中进行全区域的垃圾收集
6、GC日志
33.125: [GC [DefNew: 3324k ->152k(3712k),0.0025925 secs] 3324k->152k(11904k),0.0031680 secs]
33.125: GC发生时间
[GC:GC停顿类型,如果是 [Full GC
[DefNew: 垃圾回收器类型
3324k ->152k(3712k): GC前内存区域已使用容量-> GC后内存区域已使用容量(内存区域总容量)
3324k->152k(11904k): GC前Java堆已使用容量->GC后Java堆已使用容量
0.0025925:内存区域GC所占用时间
内存分配和回收策略
最终都是给对象分配内存和回收分配给对象的内存
对象优先在 Eden 分配
大对象直接进入老年代
长期存活的对象进入老年代
动态对象年龄判定
如果在一个 Survivor 空间中相同年龄所占内存大小占有一半,那么大于或者等于该年龄的对象直接进入老年代
空间分配担保
新生代的回收采用“复制算法”,如果没有足够的内存空间,需要老生代来担保,将一部分对象直接进入老年代,如果老年代空间还是不足,就有危险了。所以就根据以前进入老年代的对象容量大小的平均值来做个参考。通过 Fulll GC 对老年代进行一次GC,尽量腾出更多的空间。以防担保失败。
Minor Gc 和 Full GC
Minor Gc:新生代的GC,很快
Full GC:老年代的GC,慢10倍
小结
本篇了解引用的算法,由此去判断一个对象是"死”还是“活”,四种引用类型,由强至弱,生存能力越来越差,被 GC 回收的可能性也就越高。当然在一生中有唯一一次的自救机会,就是复写 finalize() 方法。进行垃圾回收时,会影响到性能。所以,出了各种回收算法以及垃圾回收器。这些各有优劣,只有适合当前环境的才是最好的。
JVM系列
1 Android 精进之简述 JVM 基础(二):Java内存区域与内存溢出异常
2 Android 进阶之简述 JVM 基础(一):走进Java
优秀人才不缺工作机会,只缺适合自己的好机会。但是他们往往没有精力从海量机会中找到最适合的那个。100offer 会对平台上的人才和企业进行严格筛选,让「最好的人才」和「最好的公司」相遇。扫描下方二维码,注册 100offer,谈谈你对下一份工作的期待。一周内,收到 5-10 个满足你要求的好机会!
END- Android 精进:简述 JVM 基础(三):垃圾收集器与内存分配策略
- JVM 垃圾收集器与内存分配策略(1)
- JVM学习系列(三)——垃圾收集器与内存分配策略
- 垃圾收集器与内存分配策略(三)
- JVM垃圾收集与内存分配策略
- JVM垃圾收集器与内存分配策略
- JVM之垃圾收集器与内存分配策略
- j深入JVM垃圾收集器与内存分配策略
- JVM-垃圾收集器与内存分配策略
- 深入理解JVM:垃圾收集器与内存分配策略
- jvm垃圾收集器与内存分配策略
- jvm垃圾收集器与内存分配策略
- jvm(3)-垃圾收集器与内存分配策略
- JVM系列2:垃圾收集器与内存分配策略
- JVM垃圾收集器与内存分配策略
- jvm笔记2--垃圾收集器与内存分配策略
- JVM(3)垃圾收集器与内存分配策略
- jvm--垃圾收集器与内存分配策略
- 第七周 项目6
- 第十周 【项目1
- numpy.array 的创建
- 自定义 View 之炫酷的成绩展示界面
- ORACLE隐式游标
- Android 精进:简述 JVM 基础(三):垃圾收集器与内存分配策略
- 第七周项目四C/C++数据结构实践——队列数组
- SQL Error: 1364, SQLState: HY000
- myeclipse把选中的字母转换成大写或者大写转小写
- OCLint自定义规则的调试方法
- 深度学习框架TensorFlow学习与应用(二)——非线性回归、MINST数据集分类
- 第十一周 【项目1-图基本算法库】
- 桥接模式下配置静态IP
- 第九周项目一 二叉树算法库