JVM 学习之Heap 知识

来源:互联网 发布:cmd 关闭端口 编辑:程序博客网 时间:2024/06/07 17:00
new 指令的执行:
1、检查这个指令的参数是否能在常量池中定位到一个类的符号应用
2、检查这个符号引用代表的类是否已被加载、解析和初始化
3、如果无,那必须先执行相应的类加载过程

使用Serial、ParNew、等带Compact 过程的收集器时,系统采用的分配算法是指针碰撞
使用CMS 这种基于Mark-Sweep 算法的收集器时,通常采用空闲列表
- 指针碰撞:Java堆中内存是绝对规整的,所有用过的内存放一边,空闲的放一边,中间放着一个指针作为分界的指示器,分配内存时仅仅是把那个指针向空闲空间那边挪动一段与对象大小相等的距离。
- 空闲列表:Java堆中内存并不是规整,已使用内存和空闲内存相互交错,由虚拟机维护一个列表,更新列表上的记录。

解决分配内存时线程安全问题方案:
1、对分配内存空间进行同步 —— 采用 CAS 配上失败重试的方式保证更新操作的原子性
2、把内存分配的动作按照线程划分在不同的空间之中进行 —— 本地线程分配缓冲

引用类型:
● 强引用:Object object = new Object(); 只要引用存在,永远不会被回收
● 软引用:描述一些还有用但并非必须的对象。在内存溢出之前,列出二次回收范围。通过SoftReference 类来实现软引用
● 弱引用:也是描述非必须的对象,弱于软引用。当垃圾收集器工作时,无论当前内存是否足够,都会收回只被弱引用关联的对象。通过 WeakReference 类来实现软引用
● 虚引用:最弱的引用关系。无法通过虚引用取得一个对象实例,唯一目的是能在这个对象被收集器回收时收到一个系统通知。通过 PhantomReference 类来实现软引用

生存与死亡:
死亡:需经历两次标记过程
- 如果对象在进行可达性分析后发现没有与GC Roots 相连接的引用链,将会被第一次标记且进行一次筛选。
筛选:(是否有必要执行 finalize() 方法)
1、当对象没有覆盖 finalize() 方法
2、finalize() 方法已经被虚拟机调用过
- 筛选的条件如果是有必要执行 finalize() 方法,则会放置一个叫做 F-Queue 的队列中。
- finalize() 方法中是否有 this 对象重新与引用链上的任何一个对象建立关联
- GC 对 F-Queue 中的对象进行二次标记,并判断是否移除“即将回收”的集合
注意: finalize() 方法只会被系统自动调用一次

方法区回收:
“无用的类”判断条件:
● 该类的所有的实例都已经被回收(Java 堆中不存在该类的任何实例)
● 加载该类的 ClassLoader 已经被回收
● 该类对应的 java.lang.Class 对象没有在任何地方被引用(无法在任何地方通过反射访问该类的方法)