java 垃圾回收总结(可达性分析 引用分类
java 垃圾回收总结(1)
以前看过很多次关于垃圾回收相关的文章,都只是看过就忘记了,没有好好的整理一下,发现写文章可以强化自己的记忆。
java与C,c++有很大的不同就是java语言开发者不需要关注内存信息,不会显式的直接操作内存,而是通过jvm虚拟机来实现。
java虚拟机运行的时候内存分配图如下图:
jvm虚拟机栈:一个是线程独有的,每次启动一个线程,就创建一个jvm虚拟机栈,线程退出的时候就销毁。这里面主要保存线程本地变量名和局部变量值。
本地方法栈: 调用本地jni方法的时候而创建的。这里分配的jvm之外的内存空间。方法调用结束之后销毁。
pc寄存器 : 这个保存线程当前执行的字节码指令
堆:主要保存创建的对象。
方法区:保存class相关的信息。主要是class的一个内存结构信息
常量池:方法区的一部分,主要保存class内存结构中常量值 例如String值,public static final 类型的值
我们这里说的垃圾回收,主要是java虚拟机对堆内存区域的回收。
1 首先的问题是:jvm如何知道那些对象需要回收 ?
目前有两种算法
- 引用计数法
每个对象上都有一个引用计数,对象每被引用一次,引用计数器就+1,对象引用被释放,引用计数器-1,直到对象的引用计数为0,对象就标识可以回收
这个可以用数据算法中的图形表示,对象A-对象B-对象C 都有引用,所以不会被回收,对象B由于没有被引用,没有路径可以达到对象B,对象B的引用计数就就是0,对象B就会被回收。
但是这个算法有明显的缺陷,对于循环引用的情况下,循环引用的对象就不会被回收。例如下图:对象A,对象B 循环引用,没有其他的对象引用A和B,则A和B 都不会被回收。
- root搜索算法
这种算法目前定义了几个root,也就是这几个对象是jvm虚拟机不会被回收的对象,所以这些对象引用的对象都是在使用中的对象,这些对象未使用的对象就是即将要被回收的对象。简单就是说:如果对象能够达到root,就不会被回收,如果对象不能够达到root,就会被回收。
如下图:对象D访问不到根对象,所以就会被回收
以下对象会被认为是root对象:
- 被启动类(bootstrap加载器)加载的类和创建的对象
- jvm运行时方法区类静态变量(static)引用的对象
- jvm运行时方法去常量池引用的对象
- jvm当前运行线程中的虚拟机栈变量表引用的对象
- 本地方法栈中(jni)引用的对象
由于这种算法即使存在互相引用的对象,但如果这两个对象无法访问到根对象,还是会被回收。如下图:对象C和对象D互相引用,但是由于无法访问根,所以会被回收。
jvm在确定是否回收的对象的时候采用的是root搜索算法来实现。
在root搜索算法的里面,我们说的引用这里都指定的是强引用关系。所谓强引用关系,就是通过用new 方式创建的对象,并且显示关联的对象
1
|
Object obj = new Object(); |
以上就是代表的是强引用关系,变量obj 强引用了 Object的一个对象。
java里面有四种应用关系,从强到弱分别为:
Strong Reference(强引用) –>Weak Reference (弱引用) -> Soft Reference(软引用) – > Phantom Reference(引用)
Strong Reference : 只有在引用对象root不可达的情况下才会标识为可回收,垃圾回收才可能进行回收
Soft Reference : 无论其引用的对象是否root可达,在响应内存需要时,由垃圾回收判断是否需要回收。
Weak Reference :用来描述非必需对象。即使在root算法中 其引用的对象root可达到,只能生存到下一次垃圾回收之前。
Phantom Reference :无法通过虚引用获得一个对象的实例,设置虚引用的目的就是能在这个对象被收集器回收时收到一个系统通知。
下面可以看一个测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
public class ReferenceTest { public static final Map<Integer, Reference> map = new HashMap<Integer, Reference>(); public static void main(String[] args) { for ( int i = 0 ; i < 1000 ; i++) { map.put(i, new WeakReference( new ReferenceObject(i))); } int i = 0 ; for (Reference r : map.values()) { if (r.get() == null ) { i++; } } System.out.println( "被回收的对象数:" + i); } static class ReferenceObject { private int i; private byte [] b; public ReferenceObject( int i) { this .i = i; b = new byte [ 1024 * 10 ]; } } } |
这里创建大约1000个 10K的 Weak Reference 对象,最后打印的结果是:被回收的对象数:767,这里ReferenceObject如果设置为1K的话,最后的打印结果是0
这个例子并不严谨,但是却说明了被Weak Reference的对象在一定的时候会被jvm回收,但是强引用就不会出现这种状态。
java 垃圾回收总结(可达性分析 引用分类的更多相关文章
- java垃圾回收机制--可达性算法
先说一些题外话,Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区,这些区分为线程私有区和线程共享区 1.线程私有区 a.程序计数器 记录正在执行的虚拟机字节码指令地址 ...
- [译]Java 垃圾回收的监控和分析
说明:这篇文章来翻译来自于Javapapers 的Java Garbage Collection Monitoring and Analysi 在这个系列的Java垃圾回收教程中,我们将看到可用于垃圾 ...
- JAVA垃圾回收-可达性分析算法
在java中是通过引用来和对象进行关联的,也就是说如果要操作对象,必须通过引用来进行.那么很显然一个简单的办法就是通过引用计数来判断一个对象是否可以被回收.不失一般性,如果一个对象没有任何引用与之关联 ...
- Java GC系列(4):垃圾回收监视和分析
本文由 ImportNew - lomoxy 翻译自 javapapers. 目录 垃圾回收介绍 垃圾回收是如何工作的? 垃圾回收的类别 垃圾回收监视和分析 在这个Java GC系列教程中,让我们学习 ...
- Java垃圾回收机制分析
Java的堆是一个运行时数据区,类的实例从中分配空间,堆中存储着正在运行的应用程序所建立的所有对象.垃圾回收是一种动态存储管理技术.它按照特定的垃圾回收算法,自动释放掉不再被引用的对象.堆内存里垃圾的 ...
- 【Java】Java垃圾回收机制
Java垃圾回收机制 说到垃圾回收(Garbage Collection,GC),很多人就会自然而然地把它和Java联系起来.在Java中,程序员不需要去关心内存动态分配和垃圾回收的问题,这一切都交给 ...
- 转 Java虚拟机5:Java垃圾回收(GC)机制详解
转 Java虚拟机5:Java垃圾回收(GC)机制详解 Java虚拟机5:Java垃圾回收(GC)机制详解 哪些内存需要回收? 哪些内存需要回收是垃圾回收机制第一个要考虑的问题,所谓“要回收的垃圾”无 ...
- Java垃圾回收机制(GC策略)
Java垃圾回收机制(GC策略) 核心:1,哪些是垃圾?[怎么确定这个是垃圾]:2,如何回收垃圾?[怎么更好收垃圾]. Java语言相对于C++等语言有一个自动垃圾回收机制,只用管使用[实例化对象], ...
- 图解Java 垃圾回收机制
摘要: Java技术体系中所提倡的 自动内存管理 最终可以归结为自动化地解决了两个问题:给对象分配内存 以及 回收分配给对象的内存,而且这两个问题针对的内存区域就是Java内存模型中的 堆区.关于对象 ...
随机推荐
- Java NIO之内存映射文件——MappedByteBuffer
大多数操作系统都可以利用虚拟内存实现将一个文件或者文件的一部分"映射"到内存中.然后,这个文件就可以当作是内存数组来访问,这比传统的文件要快得多. 内存映射文件的一个关键优势是操作 ...
- .Net程序员学用Oracle系列(6):表、字段、注释、约束、索引
<.Net程序员学用Oracle系列:导航目录> 本文大纲 1.表 1.1.创建表 1.2.修改表 & 删除表 2.字段 2.1.添加字段 2.2.修改字段 & 删除字段 ...
- Mac 安装 Grunt
第一步:安装brew 打开http://brew.sh/登陆brewhome官网,上面有安装命令. 第二步:安装node 第一步安装成功后,命令行输入 brew install node 第三步:安装 ...
- 用备份控制文件做不完全恢复下的完全恢复(数据文件备份<旧>--新建表空间--控制文件备份<次新>--日志归档文件<新>)
为什么会使用备份的控制文件? 实际工作中主要有两种情况:第一种:当前控制文件全部损坏,而数据文件备份,控制文件备份及当前日志处于不同SCN版本,它们之间又增加过表空间(数据文件).第二种:当前控制文件 ...
- OpenGL的状态机理解
OpenGL是一种状态机模式,比如你用glEnable打开一个状态,在以后的绘图中将一直保留并应用这个状态,除非你调用glDisable及同类函数来改变该状态或程序退出.例如当前颜色是一个状态变量,可 ...
- cocos2d-x中DrawNode常见的图像绘制函数
//绘制矩形 ('起始点' , '目标点' , '填充颜色') auto rect=DrawNode::create(); rect->drawRect(Vec2(0,0),Vec2(100, ...
- trove最新命令简单分类解析
usage: trove [--version] [--debug] [--service-type <service-type>] [--service-name <service ...
- 使用node.js编写脚本将JSON数据转换为SQL语句
安装依赖模块 当node.js脚本在运行的时候,需要很多支持模块,这些模块存储在node_modules文件夹中.该脚本在执行过程中需要使用到fs.string-format两个支持模块,作用分别是: ...
- 本地win7 把数组写入 txt 文本日志 json_encode转换中文,需要加上JSON_UNESCAPED_UNICODE 不适用unicode --仅仅支持php5.4以后
json_encode 改进 为 json_encode_ex function json_encode_ex($value){ if (version_compare(PHP_VERSION, '5 ...
- 将stack翻译成"堆栈"实在是误人子弟
也不知道从何时起,也不知道是哪个"教授"还是"老师",将stack翻译成堆栈(据说台湾叫做"堆叠").窃以为,这种翻译实在是误人子弟(题外话 ...