深入理解JVM:垃圾收集器与内存分配策略
堆里面存放着Java世界差点儿全部的对象实例,垃圾收集器在对堆进行回收前。第一件事情就是要确定这些对象之中哪些还存活,哪些已经死去。推断对象的生命周期是否结束有下面几种方法
引用计数法
详细操作是给对象加入一个引用计数器。每当有一个地方引用时。计数器的值就加1,;当引用失效时。计数器就减1。不论什么时刻计数器为0的对象就 是不可能再被使用的。客观的说引用计数器算法实现简单,判定效率也非常高,在大部分情况下他都是一个不错的算法。可是引用计数器有缺陷
举个简单的样例,对象A和对象B都有字段instance,赋值命令objA.instance = objB,objB.instance=objA,除此之外。这两个对象再无不论什么引用,实际上这两个对象已经不可能再被訪问了,可是他们由于互相引用这对方。导致引用数据器不为0,无法通知CG收集器收集他们。
public class ReferenceCountingGC{
public Object instance = null;
private static final int _1MB = 1024*1024;
// 这个成员属性的唯一意义就是占点内存,以便能在GC日志中看清楚是否被回收过
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;
obj.A = null;
obj.B = null;
}
}
通过GC日志。虚拟机并没有由于这两个对象互相引用就不回收他们。这从側面说明虚拟机不是通过引用计数器来推断对象是否存活。
可达性分析算法
这个算法的基本思路是通过一系列称为“GC Roots”的对象作为起始点,从这些节点開始向下搜索。搜索走过的路径称为引用链,当一个对象到GC Roots没有不论什么引用链相连。则证明此对象是不可用的。
Java语言中。可作为GC Roots的对象包括
1、虚拟机栈(栈帧中的本地变量表)中引用的变量
2、方法区中类静态属性引用的对象
3、方法区中常量引用的对象
4、本地方法栈中JNI(Native方法)引用的对象
引用分析
假设reference类型的数据中存储的数值代表的是还有一块内存的起始地址,就称为这块内存代表着一个引用。这样的定义太过狭隘,一个对象在这样的定义下仅仅有被引用和没有被引用两种状态。对于怎样描写叙述一些“食之无味。弃之可惜”的对象就显得无能为力。我们希望能描写叙述这样一类对象,当内存空间足够时。则能够保存在内存之中。假设内存空间在进行垃圾回收后还是非常紧张,则能够抛弃这些对象。
在JDK1.2以后,Java对引用进行了扩展。将引用分为强引用、软引用、弱引用、虚引用四种,强度依次递减。
1、强引用:程序中普遍存在。比如Object obj = new Object();仅仅要强引用来,CG永远不会回收
2、软引用:描写叙述一些还实用,可是并不是必要的对象。
对于软引用的对象。在系统将要发生内存溢出之前,会把这些对象列进回收范围之中进行二次回收,假设回收了还没有足够的内存将报出内存溢出,JDK1.2之后提供了SoftReference类来实现软引用。
3、弱引用:也是描写叙述非必须对象,被弱引用的对象仅仅能生存到下一次垃圾收集之前。当垃圾收集器工作时,不管内存是否够用都会被回收,JDK1.2之后提供了WeakReference类来实现弱引用。
4、虚引用:幽灵引用或者幻影引用,最弱。一个对象是否有虚无引用的存在。全然不会对其生存时间构成影响,也无法通过虚无引用来取得一个对象实例。
生存还是死亡
即使在可达性分析算法中不可达对象,也并不是是“非死不可”的,这时候他们临时出“缓刑”之中,要真正宣告一个对象死亡。至少要经历两次标记过程:假设对象在进行可达性分析后发现没有与GC Roots相连接的引用链,那他会被第一次标记而且进行一次筛查,筛查的条件是此对象是有有必要运行finalize方法。
当对象没有覆盖finalize方法,或者finalize方法已经被虚拟机调用过,虚拟机将这两种情况视为没有必要运行。
类的Finalize方法,能够告诉垃圾回收器应该运行的操作,该方法从Object类继承而来。在从堆中永久删除对象之前。垃圾回收器调用该对象的Finalize方法。注意,无法确切地保证垃圾回收器何时调用该方法,也无法保证调用不同对象的方法的顺序。即使一个对象包括还有一个对象的引用。或者在释放一个对象非常久曾经就释放了还有一个对象,也可能会以随意的顺序调用这两个对象的Finalize方法。假设必须保证採用特定的顺序,则必须提供自己的特有清理方法。
回收方法区
方法区即为Hotspot虚拟机中的永久代,永久代的垃圾收集主要回收两部分内容:废弃常量和没用的类。以常量字符串”abc”为例,已经进入常量池,可是当前系统没有不论什么一个String对象叫做abc,换句话说就是没有不论什么String对象引用常量池中的abc,假设此时发生内存回收,这个abc常量就会被系统清理出常量池。常量池中的其它类、接口、方法、字段的符号引用也与此相似。
判定一个常量是否是废弃常量比較简单,而判定一个类是否是没用的类的条件 要苛刻的多,没用的类要满足下面条件:
1、该类全部的实例都已经被回收,Java堆中不存在该类的不论什么实例。
2、载入该类的ClassLoader已经被回收
3、该类的Java.lang.class对象没有在不论什么地方被引用。无法在不论什么地方通过反射訪问该类。
深入理解JVM:垃圾收集器与内存分配策略的更多相关文章
- 深入理解JVM - 垃圾收集器与内存分配策略 - 第三章
引用计数算法——判断对象是否存活的算法 很多教科书判断对象是否存活的算法是这样的:给对象添加一个引用计数器,每当一个地方引用它时,计数器值就加1:当引用失效时,计数器值就减1:任何时刻计数器为0的对象 ...
- jvm垃圾收集器与内存分配策略
一.垃圾回收 1.对象是否已经变为垃圾 1.1.引用计数法:给对象添加一个引用计数器,每当有地方引用它时,计数器就加1:当引用失效时,计数器值就减1:任何时刻计数器为0的对象就是不可能再被使用的. 这 ...
- 深入理解JVM-3垃圾收集器与内存分配策略
在上面一篇文章中,介绍了java内存运行时区域,其中程序计数器.虚拟机栈.本地方法栈3个区域随线程生灭:栈中的栈帧随着方法的进入和退出而有条不紊的执行着进栈出栈的操作,每一个栈帧中分配着多少内存基本上 ...
- JVM垃圾收集器与内存分配策略(一)
在前面的Java自动内存管理机制(上)和Java自动内存管理机制(下)中介绍了关于JVM的一些基础知识,包括运行时数据区域划分和一些简单的参数配置,而其中也谈到了GC,但是没有深入了解,所以这里开始简 ...
- jvm系列(二)jvm垃圾收集器与内存分配策略
众所周知,在java语言中,内存分配和回收是由jvm自动管理的.因此内存的分配和回收也是jvm三大功能之一.垃圾收集器(GC)需要完成三件事情: 哪些内存需要回收? 什么时候进行回收? 如何回收? 本 ...
- JVM·垃圾收集器与内存分配策略之垃圾收集器!
1.Serial(串行)收集器(新生代都采用复制算法) 这是个单线程的收集器:即 当他工作的时候,会停掉虚拟机所有的线程!(Stop The World)
- JVM·垃圾收集器与内存分配策略之垃圾回收算法!
1.垃圾回收算法 1.1.标记-清除算法(Mark-Sweep): 过程分为“标记”和“清除”两个过程.先将所有需要回收的目标统一标记,然后再统一清除. ...
- JVM·垃圾收集器与内存分配策略之对象是否可被回收!
1.判断对象已经死去/不再被引用. 1.1.引用计数算法:给对象添加引用计数器,有个地方引用就+1,引用失效就-1.任何时刻,引用为0,即判断对象死亡. 1.1.1.优点:实现 ...
- java虚拟机学习-JVM内存管理:深入垃圾收集器与内存分配策略(4)
Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的高墙,墙外面的人想进去,墙里面的人却想出来. 概述: 说起垃圾收集(Garbage Collection,下文简称GC),大部分人都把这项 ...
- jvm系列 (二) ---垃圾收集器与内存分配策略
垃圾收集器与内存分配策略 前言:本文基于<深入java虚拟机>再加上个人的理解以及其他相关资料,对内容进行整理浓缩总结.本文中的图来自网络,感谢图的作者.如果有不正确的地方,欢迎指出. 目 ...
随机推荐
- ArcGIS小技巧——多图层情况下交互显示效果
在使用ArcMap处理数据的过程中,通常需要对比不同图层之间的差异.或者查看影像配准情况,这时我通常会怀念ENVI中的强大的拉幕显示.闪烁.亮度和透明度显示工具...... 直到有一天,闲着没事干捣鼓 ...
- 洛谷——P1056 排座椅
https://www.luogu.org/problem/show?pid=1056#sub 题目描述 上课的时候总会有一些同学和前后左右的人交头接耳,这是令小学班主任十分头疼的一件事情.不过,班主 ...
- 初识ThreadLocal
近期公司在进行Java开发者的招聘活动,当中有一道面试题是这种:"请简单描写叙述一下ThreadLocal类的作用." 结果发现有非常多的面试者没有听说过ThreadLocal或者 ...
- stackFromBottom-listview 内容从底部开始填充
今天遇到了一个问题,就是listview虽然占满了整个屏幕,但是,当它的内容只有几条的时候,它会从底部开始显示,上面留有空白.后来进入xml发现,listview有个属性stackFromBottom ...
- 3.lombok系列3:lombok的实验类特性
转自:https://blog.csdn.net/54powerman/article/details/72516755 lombok除了已经推荐使用的基本功能,还维护了一个创新型的注解,有些功能有违 ...
- 5. Spring Boot 拦截器
转自:https://blog.csdn.net/catoop/article/details/50501696
- 【习题 6-1 UVA-673】Parentheses Balance
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 括号匹配. 栈模拟就好. 多种括号也是一样可以做的. [代码] #include <bits/stdc++.h> usi ...
- ASM学习笔记--ASM 4 user guide 第二章要点翻译总结
参考:ASM 4 user guide 第一部分 core API 第二章 类 2.1.1概观 编译后的类包括: l 一个描述部分:包括修饰语(比如public或private).名字.父类.接口 ...
- HibernateCRUD基础框架(3)-简单的和较为复杂的标准的CRUD API
优点:简单的和基础的CRUD功能可以很快实现,可以说是比较的"标准化".维护起来也很容易. 缺点:性能没有保障.不支持特别复杂的CRUD. 可以适用的场景:小型Web项目 1.Cr ...
- ORACLE RMAN备份--差异增量与累积增量的策略实例图
转自原文 ORACLE RMAN备份--差异增量与累积增量的策略实例图