`
baitian
  • 浏览: 29593 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

关于java 垃圾回收的理解

阅读更多
垃圾回收分为两大步骤:识别垃圾 和 回收垃圾
识别垃圾有两大基本方法
1.计数器法
每个对象有一个相应的计数器,统计当前被引用的个数,每次被引用或者失去引用都会更新该计数器。
优点:识别垃圾快,只需判断计数器是否为零。
缺点:增加了维护计数器的成本,无法在对象互相引用的情况下识别垃圾
因此,适用于对实时性要求非常高的系统。
2.追踪法
从根对象(例如局部变量)出发,逐一遍历它的引用。若无法被扫描到,即认定为垃圾
实际情况中一般采用该方法。

回收垃圾最重要的是要最大限度地减少内存碎片。
两种通常的方法:
1.移动活对象覆盖内存碎片,使对象间的内存空白增大。
2.拷贝所有的活对象到另外一块完整的空白内存,然后一次释放原来的内存。

通常第二种方法能够最大的减少内存碎片,但是缺点是在拷贝过程中会终止程序的运行。
引入分级的概念,通常一个程序中大部分对象的生命周期很短,只有小部分的对象有比较长的生命。而恰恰使得拷贝方法性能打折扣的是重复拷贝那些长命的对象。因此,把对象分成几个级别,在低级别呆到一定时间就将其升级。相应地越高级别,回收的次数越少。最理想的情况是,每次回收最低级别的对象全部失效,一次性就可以回收该级别所有内存,提高效率。同时,由于每次只回收一个级别,不需遍历所有对象,控制了整个回收的时间。

由于垃圾识别是通过识别引用来达到,为了增加程序对垃圾回收的控制。提供了引用对象的概念,细化了引用的类型,分别是StrongReference,SoftReference, WeakReference, PhantomReference。其中强引用就是普通的java引用,其他三种类型相当于一个包装器,一方面使得垃圾回收器区分引用类型做不同的处理,另一方面程序通过他们仍然可以得到强引用。
这三种弱类型的类的结构图:


因此一个对象在它的生命周期可能有以下几种状态:strongly reachable,softly reachable,weakly reachable,resurrectable,phantom reachable,unreachable。
引用

    strongly reachable - An object can be reached from the roots without traversing any reference objects. An object begins its lifetime in the strongly reachable state and remains strongly reachable so long as it is reachable via a root node or another strongly reachable object. The garbage collector will not attempt to reclaim the memory occupied by a strongly reachable object.
    softly reachable - An object is not strongly reachable, but can be reached from the roots via one or more (uncleared) soft reference objects. The garbage collector may reclaim the memory occupied by a softly reachable object. If it does so, it clears all soft references to that softly reachable object. When the garbage collector clears a soft reference object that is associated with a reference queue, it enqueues that soft reference object.
    weakly reachable - An object is neither strongly nor softly reachable, but can be reached from the roots via one or more (uncleared) weak reference objects. The garbage collector must reclaim the memory occupied by a weakly reachable object. When it does so, it clears all the weak references to that weakly reachable object. When the garbage collector clears a weak reference object that is associated with a reference queue, it enqueues that weak reference object.
    resurrectable - An object is neither strongly, softly, or weakly reachable, but may still be resurrected back into one of those states by the execution of some finalizer.
    phantom reachable - An object is not strongly, softly, nor weakly reachable, has been determined to not be resurrectable by any finalizer (if it declares a finalize() method itself, then its finalizer will have been run), and is reachable from the roots via one or more (uncleared) phantom reference objects. As soon as an object referenced by a phantom reference object becomes phantom reachable, the garbage collector will enqueue it. The garbage collector will never clear a phantom reference. All phantom references must be explicitly cleared by the program.
    unreachable - An object is neither strongly, softly, weakly, nor phantom reachable, and is not resurrectable. Unreachable objects are ready for reclamation.

对照下面这张图来理解:


这三种弱引用的应用场合:
引用
Weak references enable you to create canonicalizing mappings, such as a hash table whose keys and values will be removed from the map if they become otherwise unreferenced by the program.

典型应用,jdk 的 WeakHashMap, ThreadLocal.

引用
Soft references enable you to create in-memory caches that are sensitive to the overall memory needs of the program. 

Phantom references enable you to establish more flexible pre-mortem cleanup policies than are possible with finalizers.



参考:
1.http://www.artima.com/insidejvm/ed2/gcP.html
2.http://www.iteye.com/topic/401478
分享到:
评论
16 楼 葬雪晴 2011-05-11  
lifeier 写道
扯这些有什么鬼用,开发中又用不着。

鄙视这种自己不会,就乱喷的人。

补充一点,我理解的垃圾回收机制。

在JAVA语言里,有自动的回收机制,让我们能很轻松的不用去理会垃圾回收,而能轻松的编程。
不像C++一样,还要去析构,不去析构就会内存溢出然后头痛的很。

JAVA里的垃圾回收机制,用的是类似有向图的监控,当一个对象完全没有了指向这个对象的引用的时候,垃圾回收机制会帮忙回收。。。由于启动垃圾回收器需要花费资源,所以不是说你想启动就启动的。所以只能是建议System.GC()

所以很多新手就认为,都机器做了垃圾回收机制,我们不需要去管,其实那只是新手的一厢情愿。

JAVA也有内存溢出,在进行队列的删除的时候如果由于只是在标记位上删除,而数组本身的某个引用还是有对象的,于是这个引用永远都不会回收。于是会造成内存溢出。

哈哈,大家多多包涵
15 楼 suhuanzheng7784877 2011-05-10  
个人觉得垃圾回收的原理还是需要知道的啊~~~~
是这样的~~
有时候确实对象在内存中的状态、周期是需要知道的~
而且弱引用、软引用等等都是在一定场合下派得上用场的~~~
一旦应用报出了内存溢出的异常也好排错嘛~
呵呵~~
http://suhuanzheng7784877.iteye.com/blog/1000646
这个希望对LZ也能有所帮助~
14 楼 laolinshi 2011-05-10  
lifeier 写道
扯这些有什么鬼用,开发中又用不着。

这只能说明你还停留在民工的水平。
13 楼 liuxuejin 2011-05-09  
解释得实在有点简单
12 楼 jwx0925 2011-05-08  
lifeier 写道
扯这些有什么鬼用,开发中又用不着。


水平低,还用不到吧~
11 楼 Rooock 2011-05-08  
关于java里的几种引用, 我觉得这篇文章言简意赅.
10 楼 safrain 2011-05-07  
lifeier 写道
扯这些有什么鬼用,开发中又用不着。

有一些场合会用到的。
9 楼 niwei 2011-05-06  
你执行一下下面的代码,将虚拟机参数设置如下:
-Xms15m -Xmx15m -Xmn10m -XX:+UseSerialGC -XX:+PrintGCDetails

public static void main(String[] args) throws Exception
	{
		byte[] b = new byte[1024 * 1024 * 5];
		SoftReference sr = new SoftReference(b);
		b = null;

		byte[] b2 = new byte[1024 * 1024 * 5];

		byte[] b3 = new byte[1024 * 1024 * 5];

		if (sr == null)
		{
			System.out.println("1");
		}
		else if (sr.get() == null)
		{
			System.out.println("2");
		}
		else
		{
			System.out.println("3");
		}
	}


你会发现在执行FullGC之后sr!=null,但sr.get()==null
8 楼 niwei 2011-05-06  
Technoboy 写道
niwei 写道
因为你已经将image置为null,有可能因为被垃圾回收而get()不到了,避免空指针。

将image设置为null,就是让GC知道,让SoftReference保存image引用,当GC检测到会抛出OutOfMemoryError时,会清理软引用,此时的image才真正的为空,并需要重新创建对象。


我的意思是你将image设置为null之后再获取时最好将(sr!=null && sr.get()!=null) 这两个判断条件都加上,因为你再次使用时可能sr!=null 但 sr.get()==null。
7 楼 Technoboy 2011-05-06  
niwei 写道
因为你已经将image置为null,有可能因为被垃圾回收而get()不到了,避免空指针。

将image设置为null,就是让GC知道,让SoftReference保存image引用,当GC检测到会抛出OutOfMemoryError时,会清理软引用,此时的image才真正的为空,并需要重新创建对象。
6 楼 niwei 2011-05-06  
因为你已经将image置为null,有可能因为被垃圾回收而get()不到了,避免空指针。
5 楼 Technoboy 2011-05-06  
baitian 写道
引用

//下次使用时
if (sr!=null) image=sr.get();
else{
//由于GC由于低内存,已释放image,因此需要重新装载;
image=new Image();
sr=new SoftReference(image);
}


if (sr!=null && sr.get()!=null)
else{
image=new Image();
sr=new SoftReference(image);
}

这样才准确把。

if判断是干啥用的呢?
4 楼 baitian 2011-05-06  
引用

//下次使用时
if (sr!=null) image=sr.get();
else{
//由于GC由于低内存,已释放image,因此需要重新装载;
image=new Image();
sr=new SoftReference(image);
}


if (sr!=null && sr.get()!=null)
else{
image=new Image();
sr=new SoftReference(image);
}

这样才准确把。
3 楼 Technoboy 2011-05-06  
lifeier 写道
扯这些有什么鬼用,开发中又用不着。

假如实现一些常用图片的缓存功能:

//申请一个图像对象
Image image=new Image();//创建Image对象

//使用 image

//使用完了image,将它设置为soft 引用类型,并且释放强引用;
SoftReference sr=new SoftReference(image);
image=null;

//下次使用时
if (sr!=null) image=sr.get();
else{
//由于GC由于低内存,已释放image,因此需要重新装载;
image=new Image();
sr=new SoftReference(image);
}

这样写,不是better一些。


2 楼 baitian 2011-05-05  
lifeier 写道
扯这些有什么鬼用,开发中又用不着。

呵呵,见谅啊!
1 楼 lifeier 2011-05-05  
扯这些有什么鬼用,开发中又用不着。

相关推荐

    Java垃圾回收知识,垃圾回收资料

    重要性:垃圾回收是Java垃圾回收器的核心功能,对性能和内存管理至关重要。准确理解垃圾回收的原理和机制,以及能够优化和调优垃圾回收过程的能力,是一个Java开发者必备的基本技能。 面试中可能会问到的垃圾回收...

    java垃圾回收知识全集

    深入理解 Java 垃圾回收对于编写高效、可靠的应用程序至关重要。以下资源将帮助您掌握 Java 垃圾回收的核心概念、工作原理以及最佳实践。 Java 垃圾回收是编写高效、稳定应用程序的关键一环。通过以上资源,您将获得...

    Java内存与垃圾回收调优.docx

    Java内存与垃圾回收调优,Java内存与垃圾回收的调优是一个重要的主题,特别是在高性能和大规模的应用程序中。以下是一些关键的调优建议和步骤: 理解内存结构: Java堆是主要的内存区域,用于存储对象实例。 堆内存...

    快速理解Java垃圾回收和jvm中的stw

    主要介绍了快速理解Java垃圾回收和jvm中的stw,涉及Java代码的停顿,jvm中的线程等相关内容,还是十分不错的,需要的朋友可以参考。

    理解Java垃圾回收

    主要帮助大家理解Java垃圾回收,通过实例学习java垃圾回收,什么是垃圾回收,感兴趣的小伙伴们可以参考一下

    成为JavaGC专家上(1)—深入浅出Java垃圾回收机制

    对于Java开发人员来说,了解垃圾回收机制(GC)有哪些好处呢?首先可以满足作为一名软件工程师的求知欲,其次,深入了解GC如何工作可以帮你写出更好的Java应用。这仅仅代表我个人的意见,但我坚信一个精通GC的人往往...

    成为JavaGC专家上(3)—深入浅出Java垃圾回收机制

    在第二篇《》,我解释了JVM实际上是如何执行垃圾回收的,我们如何监控GC,以及那哪些具可以让我们的工作更快,更高效。在第三篇文章中,我们会基于实际的例子来解释一些优化GC的最佳实践。我认为在阅读本篇文章之前...

    关于java内存管理的一些理解

    主要关于java虚拟机的运行时数据区域,参考了周志明的深入理解java虚拟机,还涉及到了native方法、垃圾回收机制等等。

    JVM常用垃圾回收器的特性与使用场景.md

    该文档总结了JVM主要的七种垃圾回收器特点与区别,分别描述了他们作用于堆内存的哪些区域,采用单线程还是多线程工作方式,在运行过程中是否需要暂停其他用户工作线程。是笔者对周志明老师的《深入理解java虚拟机》...

    深入理解JVM垃圾收集算法与垃圾收集器

    深入理解JVM垃圾收集算法与垃圾收集器

    深入理解Java垃圾回收机制以及内存泄漏

    下面小编就为大家带来一篇深入理解Java垃圾回收机制以及内存泄漏。小编觉得挺不错的,现在就分享给大家,也给的大家做个参考。一起跟随小编过来看看吧

    简单理解Java的垃圾回收机制与finalize方法的作用

    主要介绍了简单理解Java的垃圾回收机制与finalize方法的作用,着重讲解了Java的GC销毁对象的过程,需要的朋友可以参考下

    Java 虚拟机学习笔记:Java 内存区域,垃圾收集,内存分配与回收策略,JVM 调优,文件结构,类加载机制,Java 程序

    Java编程语言的语法类似于C++,但是相比C++更简洁和易于理解。它采用了“一次编写,到处运行”的原则,即一次编写的程序可以在不同的操作系统上运行,这得益于Java虚拟机(JVM)的存在。JVM是Java的核心组成部分,它...

    深入java虚拟机

    1.3 JVM调优总结(三)-基本垃圾回收算法 1.4 JVM调优总结(四)-垃圾回收面临的问题 1.5 JVM调优总结(五)-分代垃圾回收详述1 1.6 JVM调优总结(六)-分代垃圾回收详述2 1.7 JVM调优总结(七)-典型配置举例1 1.8 ...

    java技术—让学员少走弯路

    Java中包的概念,类的说明符、方法的说明符、对象的销毁(JVM垃圾回收器的演示),Java中接口理解与掌握。 Java中包的概念,类的说明符、方法的说明符、对象的销毁(JVM垃圾回收器的演示),Java中接口理解与掌握。

    笔记,2、内存分配与回收策略~深入理解垃圾回收器1

    3、写代码有好处栈:栈中的生命周期是跟随线程,所以一般不需要关注堆:堆中的对象是垃圾回收的重点方法区/元空间:这一块也会发生垃圾回收,不过这块的效率比较低,一般

    预习,2、内存分配与回收策略~深入理解垃圾回收器1

    3、写代码有好处栈:栈中的生命周期是跟随线程,所以一般不需要关注堆:堆中的对象是垃圾回收的重点方法区/元空间:这一块也会发生垃圾回收,不过这块的效率比较低,一般

    理解JAVA虚拟机-内存管理、垃圾收集器.pptx

    讲解java虚拟机 包括内存模型,内存管理,垃圾回收算法,垃圾回收调优,arthas、jmap内存问题排查

    从blink里剥离的垃圾回收组件, 能让c++拥有java一样的自动垃圾回收机制.zip

    在进行毕业设计、课程设计或大作业时,选择具备学习借鉴价值的项目可以帮助你理解和应用所学知识,同时也可以通过修改和扩展来实现其他功能。 通过参与实际项目,你可以应用所学的理论知识,深入了解软件开发或其他...

    垃圾回收finalize的用处(算法 演示)

    对于一个JAVA程序员来说内存就是生命,如果出现内存泄露,或者内存不能释放,那程序就危险了,虽然JAVA有垃圾回收,但是你如果真的理解垃圾回收的原理,就应该看看这个!

Global site tag (gtag.js) - Google Analytics