JVM垃圾回收总结

导语

对JVM中的知识点进行归纳总结,内容并不详细,如果需要深入了解,请看文中的链接

运行时数据区

JAVA内存分布

方法区域(线程共享):类文件存储区
堆区(线程共享):存放对象实例
虚拟机栈(线程独占):通常所说的栈内存,线程执行函数的地方。每个函数对应一个栈帧,栈帧存放本地变量表。
本地方法栈(线程独占):C或C++执行时使用的栈,也叫Native栈
程序计数器(线程独占):线程在运行时,指向下一条指令在内存中的位置

对象的创建

类加载:将类文件加载到内存中
内存分配:为对象分配内存,JVM对内存进行管理时使用指针碰撞或空闲列表法
内存初始化操作:将内存初始化为0
对象头的设置:对象头中包含这个对象是哪个类的实例,如何才能找到类的元数据信息,对象哈希码等信息,需要对这些信息进行设置

对象的内存布局

对象在内存中存储分为以下三块:

  • 对象头:存储对象自身的运行时数据,包括哈希码,GC分代年龄,锁状态标志,线程持有的锁等,对象头占据内存空间的大小是固定的,但是其需要存储的内容比分配的空间大,所以会存储空间复用的情况
  • 实例数据:该部分是对象真正存储的有效信息,也就是程序代码中所定义的各种Fields。但是值得注意的是,我们代码中定义的域的顺序,和存储时的顺序并不是一致的。因为数据存储时有字节对齐的问题,所以JVM会尽量将相同宽度的自己放在一起。
  • 对其填充:HotSpot要求对象的大小必须是8字节的倍数,所以需要填充对其。

访问对象

Java中通过引用来访问对象,引用被称为Reference。至于如何通过引用来获取对象有以下两种方式:

  • 句柄:使用句柄来访问对象时,则会在堆中划分出一块区域作为句柄池,Reference中保存句柄池中某个句柄的地址,通过该地址访问句柄,通过句柄访问该对象。而句柄中包含对象实例数据指针和对象类型数据指针。
  • 直接指针:Reference中直接存放对象的地址,这种情况下访问对象速度快,HotSpot基于该方法实现。

对象的回收

当对象状态不可达时,该对象将被回收。具体而言就是GC会回收那些不是GC roots且没有被GC roots引用的对象。一个对象可以属于多个GC ROOT,下面是常见的GC ROOT:

  • 虚拟机栈(栈帧中的本地变量表)中引用的对象;
  • 方法区中静态属性引用的对象
  • 方法区中常量引用的对象
  • 活着的线程

没有在GC ROOT链上的对象被认为对象处于不可达状态。那么对象处于不可达状态后是否就能马上被回收呢?其实在回收一个不可达状态的对象时需要经过两次标记:第一次标记是将不处于GC ROOT链且没有实现finalize()或该方法被JVM执行过的对象进行一次标记,这样的对象是一定要被回收的。对于那些不可达且实现的finalize()方法没有被执行的对象将会放到F-QUEUE队列中。JVM会开启一个线程来执行位于该队列中每个对象的finalize(),如果对象能够在自己的finalize()中将自己重新挂到ROOT上,那么可以避免被回收了。注意:finalize()能且只能被执行一次。

方法区的回收(无用的类,常量)

无用的类回收条件:该类的所有实例已经被回收,classLoader已经被回收,该类对应的Class对象已被被回收。

垃圾回收器算法

  • 标记-清除算法:先对被回收的对象进行标记,然后统一回收。缺点是效率低,产生内存片
  • 复制算法:适用对象新生代,Eden区(8),Survivor区(1),分配担保(老年代)
  • 标记-整理:对象老年代,对象标记,内存压缩

HotSpot垃圾回收

在进行垃圾回收的时候,首先需要找打GC ROOT。静态数据和final数据都在方法区,作为GC ROOT很容易查找。但是在查找局部变量引用时就比较困难。HotSpot中使用OOPMap来存储对象引用。

垃圾回收器

新生代回收器

  • Serial收集器:暂停用户线程,开一线程回收垃圾
  • ParNew收集器:serial收集器的多线程版本
  • Parallel Scavenge收集器:复制算法,多线程

前两个关注减少用户线程停顿时间,第三个关注提高系统吞吐量

老年代回收器

  • Serial old收集器:单线程,标记整理法,暂停用户线程
  • Parallel old收集器: Parallel Scavenge的老年代版本
  • CMS收集器:以获取最短回收停顿时间为目标的收集器,采用标记清楚算法。需要进行两次停顿(初始标记,重新标记),但时间很短,其进行垃圾回收时是与用户线程同时工作的。

G1收集器

G1收集器是一款面向服务端应用的垃圾收集器。它是新一代的收集器。与其它收集器相比,G1具备以下特点:

  • 并行与并发:G1能充分利用多CPU、多核环境下的硬件优势,使用多个CPU来缩短Stop-The-World的停顿时间。
  • 分代收集:分代概念在G1中继续保留,但G1能独立管理整个GC堆
  • 空间整合:G1从整体看是基于“标记-整理”算法,但从局部看是基于“复制”算法实现的。

参考博客

java面试集合
http://blog.csdn.net/hsk256/article/details/49104955

JVM垃圾回收
http://jbutton.iteye.com/blog/1569746

JVM内存模型
http://www.cnblogs.com/nexiyi/p/java_memory_model_and_thread.html

posted @ 2017-02-18 15:09  被罚站的树  阅读(348)  评论(0编辑  收藏  举报