《深入理解Java虚拟机》——内存自动管理:内存分配与回收
来源:互联网 发布:asp.net 的优势php 编辑:程序博客网 时间:2024/06/06 20:15
标签(空格分隔): JVM
先讲讲自动内存回收——GC
GC的三大问题——What & When & How
- 哪些内存需要回收?
- 何时回收?
- 如何回收?
什么是内存溢出,内存泄露?
GC的三大问题(一)——哪些内存需要回收?
回收区域:Java堆和方法区(对象的创建是动态的,不确定性)(线程私有区域不考虑)回收对象:“死亡的”对象实例
如何定义“死亡”(Java堆)
1. 引用计数法
引用计数器简单,效率高,不可靠无法解决“对象之间循环引用”
/*示例代码*/public class ReferenceCountingGC { public ReferenceCountingGC instance = null; private static final int _1MB = 1024 * 1024; private byte[] bigSize = new byte[2 * _1MB]; public static void testGC() { ReferenceCountingGC objA = new ReferenceCountingGC(); ReferenceCountingGC objB = new ReferenceCountingGC(); objA.instance = objB; objB.instance = objA; objA = null; objB = null; System.GC(); }}
2. 可达性分析
GC Roots + 引用链被Java采用在Java中,可作为GC Roots的对象有: 1. 2. 3. 4.
3. 引用类型:强软弱虚
Java中引用的定义: 如果reference类型的数据中存储的数值代表的是另外一块内存的起始地址,就称这块内存代表中一个引用。判断对象存活仅与引用有关,太过”狭隘““食之无味,弃之可惜”——缓存
如何定义“死亡”(方法区)
废弃常量
1. 常量池中的常量不被引用
无用的类
1. 该类的所有实例都已经被回收——Java堆中不存在该类的实例 2. 加载该类的ClassLoader已经被回收3. 该类对应的java.lang.class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法
GC的三大问题(二)——何时回收?
两个阶段: 1.第一次标记 2.第二次标记
第一次标记:
1. 可达性分析:若某一对象“不可达”,则标记2. 筛选: 若对象被选中,则加入F-Queue队列 当对象未覆盖finalize()方法或者此方法已经被虚拟机调用过,则不被选中
第二次标记:
3. GC对F-Queue队列中的对象执行第二次小规模标记 对象在finalize()中实现“自我拯救”,退出F-Queue队列4. 虚拟机自动建立”低优先级“的Finalizer线程执行回收动作——调用对象的finalize()方法
“自我拯救”????
public class FinalizeEscapeGC { public static FinalizeEscapeGC SAVE_HOOK = null; public void isLive() { System.out.println("I am still alive!"); } @Override protected void finalize() throws Throwable { super.finalize(); System.out.println("finalize method executed!"); SAVE_HOOK = this; } public static void main(String[] args) { SAVE_HOOK = new FinalizeEscapeGC(); /* 实现自我拯救 */ SAVE_HOOK = null; System.GC(); Thread.sleep(500); if (SAVE_HOOK != null) { isLive(); } else { System.out.println("I'm dead!"); } /* finalize()只能执行一次 。不会被回收???? */ SAVE_HOOK = null; System.GC(); Thread.sleep(500); if (SAVE_HOOK != null) { isLive(); } else { System.out.println("I'm dead!"); } }}
finalize()
Forget it!
GC的三大问题(三)——如何回收?
GC算法
1. Mark-Sweep:效率低 + 内存碎片多 适合对象存活率较高的情况,适合回收老年代2. Copying:把活着的对象复制到另一块内存空间,再清理已使用的那块; 适合对象存活率较低的情况,被主流商业虚拟机采用回收新生代。(“朝生夕死”) Eden:Survivor:Survivor = 8:1:1,每次新生代可用内存空间占整个新生代容量的90% 老年代分配担保(Handle Promotion)3. Mark-Compact:让存活的对象向内存的一端移动,直接清理掉端边界以外的内存; 适合对象存活率较高的情况,适合回收老年代4. Generational Collection “因地制宜”
Hotpot的GC算法实现
我们始终关注算法的执行效率!
枚举根节点
安全点
安全区域
垃圾收集器(了解)
GC日志(了解)
内存分配策略
1. 大多数情况下,对象在新生代的Eden区上分配。当Eden区上没有足够空间时,虚拟机发起一次 Minor GC(Copying)2. 大对象直接进入老年代 需要大量连续内存空间的Java对象,例如很长的字符串和byte[4 * _1MB] "朝生夕死"的“短命大对象”是JVM最不想看到的,写程序也应尽量避免 经常出现大对象导致内存即使仍有不少空间,也需要提前触发GC以获得足够多的连续空间3. 长期存活的对象将进入老年代 对象年龄计数器。 如果对象在Eden区出生,经过第一次Minor GC后仍然存活,并且能被Survivor区容纳,将被移动到Survivor空间中,对象年龄变为1. 接下来,对象在Survivor区每“熬过”一次Minor GC,年龄加一,到达阈值(15),进入老年代4. 动态对象年龄判定 如果Survivor空间中相同年龄的所有对象大小的总和大于Survivor空间的一半,年龄大于等于该年龄的对象可以直接进入老年区,无需达到“阈值年龄”!5. 空间分配担保
阅读全文
0 0
- 《深入理解Java虚拟机》——内存自动管理:内存分配与回收
- 深入理解Java虚拟机笔记---内存分配与回收策略
- 深入理解java虚拟机-3 内存分配与回收策略
- 深入理解Java虚拟机笔记---内存分配与回收策略
- 深入理解Java虚拟机 三、内存分配与回收
- 深入理解java虚拟机-内存分配与回收策略
- 《深入理解Java虚拟机》——垃圾回收与内存分配
- 《深入理解Java虚拟机》读书笔记——内存分配与回收策略
- [深入理解Java虚拟机]第三章 内存分配与回收策略
- 深入理解java虚拟机读书笔记-3.6内存分配与回收策略
- 深入理解JAVA虚拟机(三)内存分配与回收机制
- 《深入理解Java虚拟机》学习笔记(3)--内存分配与回收策略
- 虚拟机内存管理—深入理解Java虚拟机(三)
- 【笔记】深入理解 java 虚拟机---内存回收
- JAVA虚拟机内存分配与回收机制
- JAVA虚拟机内存分配与回收机制
- JAVA虚拟机内存分配与回收机制
- Java虚拟机 - 对象内存分配与回收
- luoguP1781 宇宙总统 题解
- position:absolute与position:relative的区别
- SVN 新的认识
- openshift/origin学习记录(7)——集成Jenkins服务
- jquery实现图片左右间隔滚动特效(可自动播放)
- 《深入理解Java虚拟机》——内存自动管理:内存分配与回收
- cron 表达式详解
- 遍历二叉树的各种操作(非递归遍历)main函数
- 【枚举】HDU1164Eddy's research I
- 2017.9.12 连通数 失败总结
- HDU6070 Dirt Ratio (01规划+线段树)
- 【Paper Note】Very Deep Convolutional Networks for Large-Scale Image Recognition——VGG(论文理解)
- 第三方开源库:TabLayout相关
- startActivityForResult调用后立即响应了OnActivityResult()方法,导致setResult()后无响应