1,jvm在何时决定回收一个java 对象所占据的内存:?
2,jvm会不会漏掉回收某些java对象,使其造成内存泄漏?
3,jvm回收java对象得实现细节。?
4,jvm能否对不同java对象占用的内存区分对待,回收?
1,判断一个对象是否可回收得标准就是在于该对象是否被引用。
2,java对象得引用分为如下几种;
强引用, 软引用 弱引用和 虚引用
jvm的垃圾回收机制采用有向图的方式来管理内存中的对象。当一个对象不可到达的时候就可以把它回收。
对象的三种状态,可到达 可恢复 不可达
强引用:这是java最常见得引用方式,程序创建一个对象,并且把一个对象赋给一个引用变量,这个引用变量就是强引用。被强引用所引用的对象绝对不会被垃圾回收机制回收,即使系统内存非常紧张。因此强引用是造成java内存泄漏得主要原因之一。
软引用:软引用需要通过SoftReference类来实现。当一个对象只具有软引用的时候,它就有可能被垃圾回收机制回收,对于只有软引用的对象而言,当系统内存控件足够时,它不会被系统回收,当不够时,就会被回收。当系统内存空间足够时,强引用和软引用没有太大得区别。
弱引用:弱引用和软引用类似,但是弱引用的生存周期更短。当系统垃圾回收机制运行时,不管系统内存是否足够,总会回收该对象所占用的内存。
如果存在没有用,但是有没有回收得内存,那就是内存泄漏;例如arrayList中移除一个元素,必须将这个元素释放。 element[--size]=null
3,内存回收机制主要完成两件事情。
1,跟踪并且监控每一个java对象,当某一个对象处于不可到达得状态时,回收该对象所占用的内存,2,清理内存分配,回收过程中产生得内存碎片。
2,垃圾回收得基本算法,压缩,复制,等等。。
根据对象生存时间的长短,把堆内存分为3代;
young,old。permanent。不同代得特点采用不同得回收算法。
堆内存得分代回收:
分代回收得一个依据就是对象生存时间的长短,然后采用不同的垃圾回收策略; 这些策略基于一下事实。
绝大多数的对象是不会被长时间引用,这些对象在其young期间就会被回收
很老的对象和很新得对象之间很少存在相互引用。
对于young代,采用复制算法只需遍历那些处于可达状态得算法。而且这些对象数量少,复制成本不大。
对于old代,空间相对较大,没那么容易死,而且对象多,所以对于old对象,回收的频率不用太高,因此很少对象会死掉。每次对old代码执行垃圾回收需要更长的时间来完成。
所以它一般采用标记压缩算法。
对于permanent代,主要用于装在class,方法等信息,默认时64M。垃圾回收机制通常不会回收permanent代中的对象,对于那些需要加载很多类的服务器程序,旺旺需要加大permanent代内存,否则可能因为内存不足而导致程序终止。
当young内存快要用完的时候,垃圾回收机制会对young代进行垃圾回收,垃圾回收机制会采用较高得频率对young代进行扫描和回收,因此这种回收得开销比较小,因此被称为次要回收(minor collection)当old代的内存块要用完的时候,垃圾回收机制会进行全回收,也就是对young和old都要进行回收,这样的回收成本就大的多,因此,也称之为主要回收(major collection)。
常见的垃圾回收器:串行回收器,并行回收器,并行压缩回收器···等等
内存管理上的小技巧:
1,尽量使用直接量,不要用new的方式来创建,而是直接使用直接量
例如:用String str="hello" 而非String str=new String("hello")
2,使用StringBuilder和StringBuffer进行字符串连接。
3,尽早释放无用对象的引用。
public void info(){ Object obj=new Object(); sysout(obj.toStirng()); obj=null; }
上面的obj=null是没有必要的,因为obj引用对象得作用域结束,原来的obj就会变成垃圾。
public void info(){ Object obj=new Object(); sysout(obj.toStirng()); obj=null; //需要执行耗时,耗内存操作 }
此时obj=null时有必要的,尽早得释放对Object的引用。在执行耗时操作的时候,Obj对象可能被垃圾回收。
4,尽量少使用静态变量:
class Person{ static Object obj=new Object(); }
垃圾回收机制通常不会回收这个对象所占用的内存的。对于Object而言,只要obj变量还引用它,他就不会被垃圾回收机制所回收。obj变量时Person类的静态变量,因此它的生命周期与person类同步在person类不被卸载得情况下,Person类对应的Class对象会常驻内存。知道程序运行结束,所以obj所引用的object对象一旦被创建。也会常驻内存,知道程序运行结束。
5,避免在京藏调用的方法,循环中创建java对象
例如:
public static void main(String[] args) { for(int i=0;i<10;i++){ Object obj=new Object(); / /执行其它操作 } }
循环导致Object会被创建10次,因此系统需要为这十个对象分配内存控件,执行初始化操作,这是个对象的生存周期不长,接下来系统又需要不断的回收他们说占的内存空间,这种不断的分配,回收操作中程序得性能会受到很大的影响。
6,缓存经常使用得对象
实现缓存的两种方式:1,使用HashMap进行缓存。2,直接使用某些开源缓存项目;(例OSCache,他们大都实现了FIFO,MRU等算法,按照算法来淘汰容器中不需要得缓存对象) 缓存本身就是一种以空间换时间的技术;
缓存设计的关键:如何控制该容占用的内存不至于过大,而该容器又能保留大部分已用过的对象;
原文:http://my.oschina.net/u/2480757/blog/517006