JVM内存回收区域+对象存活的判断+引用类型+垃圾回收线程


此文已由做者赵计刚薪受权网易云社区发布。html

欢迎访问网易云社区,了解更多网易技术产品运营经验。前端


注意:本文主要参考自《深刻理解Java虚拟机(第二版)》java

说明:查看本文以前,推荐先知道JVM内存结构,见《第一章 JVM内存结构安全

一、内存回收的区域服务器

  • 堆:这是GC的主要区域框架

  • 方法区:回收两样东西测试

    • 无用的类spa

    • 废弃的常量.net

  • 栈和PC寄存器是线程私有区域,不发生GC线程

 

二、怎样判断对象是否存活

垃圾回收:回收掉死亡对象所占的内存。判断对象是否死亡,有两种方式:

  • 引用计数法

    • 每次为对象赋值时,都要进行计数器值的增减,消耗较大

    • 对于A、B相互引用这种状况处理不了(这一点是不用的主要缘由)

    • 原理:给对象添加一个引用计数器,每当有一个地方引用它时,计数器值+1;引用失效时,计数器值-1

    • 实际中不用,不用的两个缘由

  • 可达性分析(跟踪收集)

    • 原理:从根集合(GC Roots)开始向下扫描,根集合中的节点能够到达的节点就是存活节点,根集合中的节点到达不了的节点就是将要被回收的死亡节点,以下图中的A/B/C是存活节点,D/E是死亡节点:



    • Java栈中的对象引用(存在于局部变量表中,注意:局部变量表中存放的是基本数据类型和对象引用)

    • 方法区中:常量+静态(static)变量

    • 传到本地方法中,尚未被本地方法释放的对象引用

    • 这是垃圾回收最多考虑的地方,因此有时,咱们也会将死亡对象称为"没有引用指向的对象"

    • 根集合中的节点包括:简单来说,就是全局性的引用(常量和静态属性)和栈引用(下边第1、三)

 

三、3种引用类型

  • 强引用(Strong Reference):A a = new A();//a是强引用

  • 软引用(Soft Reference):当内存不足时,释放软引用所引用的对象;当内存足够时,就是一个普通对象(强引用)

  • 弱引用(Weak Reference):弱引用对象只能存活到下一次垃圾回收以前,一旦发生垃圾回收,马上被回收掉

 

四、方法区的回收

  • 废弃常量:例如,没有任何一个引用指向常量池中的"abc"字符串,则"abc"字符串被回收

  • 无用的类:知足如下三个条件

    • Java堆中不存在该类的任何实例

    • 加载该类的ClassLoader被回收

    • 该类的Class对象没有在任何地方被引用

注意:

  • 在实际开发中,尽可能不用JSP去作前端,而是用velocity、freemarker这样的模板引擎去作

  • 与类相关经常使用的三个参数:

    • -XX:+PrintClassHistogram:输出类统计状态

    • -XX:-TraceClassLoading:打印类加载信息

    • -XX:-TraceClassUnloading:打印类卸载信息

 

五、垃圾回收线程

系统的垃圾回收是由垃圾回收线程来检测操做的,该线程是一个后台线程(daemon thread)。

5.一、后台线程与咱们使用的前台线程而言,有一个特色:当JVM中的前台线程数量为0时,后台线程自动消亡。能够这样讲,后台线程依托于前台线程而存在。

5.二、垃圾回收线程为何要设置成为后台线程呢?

咱们想一下,当前台一个线程都没有时,垃圾还会有吗?或者说垃圾回收还有必要吗?答案是没有必要,因此此时垃圾回收线程也就失去了存活的意义。

因此能够这样讲,将一个线程是否设置为后台线程,就看这条线程在没有其余线程存在的状况下,是否还有存活的意义。

例如,在咱们使用Apache mina2作RPC时,咱们在消息的接收端直接开启一个后台线程启动服务来接受消息发送端发来的消息事件请求就能够。试着去想,若是在整个JVM中只有当前的这一个后台线程了,那么这个线程还有必要存活下来吗?固然没有必要,由于消息永远都不会再发送了(前台线程都没了)

 

免费领取验证码、内容安全、短信发送、直播点播体验包及云服务器等套餐

更多网易技术、产品、运营经验分享请点击


相关文章:
【推荐】 [翻译]pytest测试框架(一)
【推荐】 dubbo事件通知机制(1)
【推荐】 debian 7上源码编译MongoDB 3.4版本

相关文章
相关标签/搜索