内存回收机制 在java中,内存管理包括两个方面: 内存分配(创建java对象)和 内存回收。这两个方面都是由jvm自动完成的。 java在内存中的状态先看以下代码 - import java.io.Serializable;
- public class Person implements Serializable
- {
- static final long serialVersionUTD = 1L;
- String name;
- Person friend;
- public Person(){}
- public Person(String name)
- {
- super();
- this.name=name;
- }
- }
- public class Test
- {
- public static void main(String[] args)
- {
- Person p1 = new Person("Kevin");
- Person p2 = new Person("Rain");
- Person p3 = new Person("Sunny");
- p1.friend = p2;
- p3 = p2;
- p2 = null;
- }
- }
复制代码
把上面对象引用图画成一个从 main方法开始的对象引用图就是这样的:
![]()
当程序运行起来后,把它的内存看成有向图,可以分为三种: 可达状态在一个对象创建之后,有一个以上的引用变量引用它。在有向图中可以从起始点到该对象。 可恢复状态如果程序中某个对象不再有任何的引用变量引用它(曾经有),他就可以先进入 可恢复状态,此时有向图是不能到达他的。
在这个状态下,系统的垃圾回收机制准备回收该对象所占用的内存。在回收前,系统会调用 finalize()进行资源清理。
如果资源清理后,有一个以上的引用变量 重新引用该对象,则其变回 可达状态,反正就进入**不可达状态**。 不可达状态当对象的所有联系都被切断,且系统调用finalize()方法对资源进行清理后,仍旧没有引用对象引用,则变成 不可达对象,这时系统就会真正地去回收该对象。
一图表达:
![]() java对象的四种引用强引用创建一个对象,并把该对象直接复制给一个变量,如 Person person = new Person("sunny");。
不管系统资源多么紧张,都不会回收。 软引用软引用是通过 SoftReference类实现的,如 SoftReference<Person> person = new SoftReference<Peson>( new Person("rain"))。
内存非常紧张时,会对其进行回收,其他时候则不会回收,所以在使用之前要进行null判断再使用。 弱引用弱引用是通过 WeakReference类实现的,如 WeakReference<Person> p = new WeakReference<Person>( new Person("rain") );
不管内存够不够,在进行垃圾回收时,都会进行回收。 虚引用不能单独引用,主要是用于追踪对象被垃圾回收的状态,通过 PhantomReference类和引用队列 ReferenceQueue类联合使用实现。 垃圾回收机制java垃圾回收主要做两件事, 内存回收和 碎片整理 。 垃圾回收算法串行回收和并行回收串行回收是不管系统有多少个cpu,都只用一个cpu来执行垃圾回收操作。
并行回收是把整个回收拆分成多个部分,每个部分由一个cpu负责,从而让多个cpu并行回收。
并行回收执行效率高,但是复杂度也高。 并行执行和应用停止应用程序停止(Stop-the-world):其垃圾回收时,会导致程序暂停。
并发执行的垃圾回收虽然不会导致应用程序的暂停,但由于并发执行垃圾需要解决和应用程序的执行冲突,因此开销大,而且需要更多的堆内存。 压缩和不压缩和复制支持压缩的垃圾回收器(标记-压缩 = 标记清除+压缩):会把所有的可达对象搬迁在一齐,然后将之前占用的内存全部回收,减少碎片。
不压缩的垃圾回收器(标记-清除):要遍历两次,第一先从根开始访问所有可达对象,并标记他们为可达状态;第二次便利用整个内存区域,对未标记可达状态的对象进行回收处理。
这种方式,不压缩,不需要额外内存,但要遍历两次。 (跟js的垃圾回收方式有点像)
复制式的垃圾回收器
将堆内存分成两个相同的空间,从根开始访问每一个关联的可达对象,将空间A的全部可达对象复制到空间B,然后一次性回收空间A。 内存管理小技巧- 尽量使用直接量,如 String str = "xxx"
- 使用 StringBuilder和 StringBuffer进行字符串连接等操作。
- 尽早释放无用对象
- 尽量少使用静态变量
- 缓存常用的对象,可以使用开源缓存实现(OSCache,Ehcache)
- 尽量不使用 finalize()方法
- 在必要时可以考虑软引用 (SoftReference)。
|