垃圾收集器与内存分配策略(一)

垃圾收集器与内存分配策略之--对象已死吗

GC关注的问题其实就是三个:

  • 哪些内存可以被回收
  • 何时回收
  • 如何回收

所有的GC问题都是关于这三点的描述。
对于JVM来说,首先线程独有的三块(程序计数器、栈、本地方法栈)都是随着线程的开始而创建,线程结束而消亡,一个栈帧在开始时内存已经固定,所以GC没必要处理这部分内存。我们所说的GC都是针对堆和方法区而言的。

对象已死吗

如何判断一个对象已死?一般主流两种方法:引用计数法和可达性分析法

引用计数法

很简单,每个对象维护一个引用计数器,当某个引用指向这个对象时,就让这个引用计数器加1。当一个对象的引用计数器为0,说明对象已死。
致命的缺点:
不好解决循环引用问题。

可达性分析法

通过一组“GC Root”的对象作为起始点,向下搜索,走过的路径上的每个对象是还活着的。不可达的对象就是死的。HotSpot用的就是这个方法。
Java中可被作为GC Root的对象有四种:

  • 栈中引用指向的对象
  • 方法区中static引用指向的对象
  • 方法区中常量引用指向的对象
  • 本地方法栈中引用指向的对象

再谈引用

一般我们说的引用都是指强引用。

Object obj = new Object();//obj就是一个强引用

而Java中引入一些“弱”的引用。目的为了引入一种这样的对象:当内存足够时,对象保留内存中,当内存不够时,这些对象可被回收。
Java里引用分为四种:强引用、软引用、弱引用、虚引用。引用强度逐渐减弱。
这四种引用的区别就是指向的对象的生存时间不一样。

  • 强引用
    这个就是我们普通说的引用,如果一个对象存在这种引用。即时内存要溢出,这些对象也不能被回收。
  • 软引用
    在要发生内存溢出之前,会先将这些引用指向的对象回收调。(其中这种说法不对,应该是一个对象只有软引用指向它时)。
    比如我们定义一个软引用:
SoftReference<String> s = new SoftReference<String>(new String("123"));
  • 弱引用
    生命周期为下一次GC之前。无论内存是否足够,这些指向的对象都会被回收。
WeakReference<String> w = new WeakReference<String>(new String("234"));
  • 虚引用
    一个对象是否有虚引用和它的生命周期毫无关系。虚引用的唯一目的就是在对象被回收的时候会受到一个系统通知。
ReferenceQueue<String> referenceQueue = new ReferenceQueue<String>();
PhantomReference<String> p = new PhantomReference<>(new String("434"), referenceQueue);//当对象被回收时,referenceQueue就会受到一个消息

一般软引用和弱引用都用于本地缓存中,每次用时判断一下是否被回收,如果被回收再去到数据库里捞。

SoftReference<String> s = new SoftReference<String>(new String("123"));
if (null == s.get()) {//如果已被回收
    //到数据库里捞
}else {//如果没被回收
    System.out.println(s.get());//直接使用
}

生存还是死亡

一个对象GC Root不可达并不代表着立刻死亡。一个对象的死亡要经历两次标记。
具体过程如下:


对象死亡过程
  • 当GC Root不可达之后被标记一次,
  • 然后判断这个对象是否需要执行finalize方法。
    判断不需要的标准是:对象没有重写finalize方法或finalize已被虚拟机执行过。[也就是说对象finalize只能被执行一次]
  • 如果判断需要执行,则将这个对象丢到F-Queue中,然后虚拟机会有一个Finalize线程去消费执行对象的finalize方法,但并不会等待执行结束。如果在执行finalize方法中[在被标记第二次之前]又把此对象关联到GC Root上,这个对象就又会活过来。【注意这种现象一个对象只能出现一次,因为finalize方法只可能会执行一次】
  • 所以说一个对象的finalize被执行了,这个对象可能还是活着的。且finalize方法被强烈建议不要使用,这个方法不会有人保证它是否会执行、何时执行、何时执行结束。

回收方法区

回收方法区的性价比很低,且Java虚拟机规范中并没有强制要求要回收方法区。
回头方法区主要回收两点:常量和无用的类。

  • 常量
    这里说的就是常量池中常量,比如字面量和符号引用。
    判断是否应该回收比较简单,比如字面量:系统中没人叫这个东西了,自然就可以被回收了。
  • 无用的类
    这个判断起来就比较麻烦了。
    主要由三点:
    该类的实例已全部被回收
    加载该类的ClassLoader已被回收
    该类的Class对象无引用且无法使用反射来调用
    满足这三点是可以被回收,但也不是一定就会被回收。可以使用-Xnoclassgc来控制。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341

推荐阅读更多精彩内容