Java之内存回收

  学习Java的过程是比学习C++和C来得轻松地多,从某种程度上来讲,和JVM自带的垃圾回收机制有关,在C或者C++中创建完数组后需要手动来进行释放,一不小心就会发生内存的泄露。JVM帮助我们自动回收不用的内存,当然,这个是以效率来换的。

  JVM如何判断某个实例是否应该被回收掉呢?有两种方式:

  一、引用计数法:当某个实例被一个对象引用时,那个实例的计数器就会加1,当实例中的计数器为0时,说明没有被对象引用,这个时候JVM就可以将这个实例的空间释放掉。但这样有一个问题,如果两个实例相互引用,而这两个实例又都不会再被用到了,采用这种方法这两个实例是释放不了的。

  二、可达性分析方法:这种方法就比较高级了,它从main开始,为所有的实例建立一条可达的通道,如果某个实例处于不可达的范围,那么该实例就可以被释放掉。JVM在释放内存时会给即将被释放的实例一个自救的机会,如果实例复写了finalize()方法,那么实例会被放到一个队列中,执行finalize()方法,如果自救没有成功,那么就直接释放掉它所占用的内存。

  

  Java中引用对象的方式有4种,分别是强引用、软引用、弱引用以及虚引用,下面是他们的一些区别:

  1、强引用:使用频率最多的一种方式,正常的使用应该都属于强引用,不管系统的资源有多紧张,强引用的对象都不会被释放。

  2、软引用:使用方法是SoftReference<Person> p = new SoftReference<Person>(new Person("Rain"));在系统资源紧张时,软引用的对象会被回收。

  3、弱引用:使用方法是WeakReference<Person> p = new WeakReference<Person|>(new Person("Rain"));弱引用是在内存回收时肯定会被回收的。

  4、虚引用:这个比较特殊,虚引用是和ReferenceQueue结合使用的,它不能被单独使用,当被虚引用标注的实例被回收后,实例就被放入队列中,以此来追踪实例被垃圾回收的状态。

  关于JVM中的垃圾回收算法和方式,先来了解一些基本概念:

  1、串行回收:相当于只有一个线程在回收资源。

  2、并行回收:是多个线程在协同工作,回收资源。

  3、并发执行:指当回收的工作开始时,所有的Java应用程序都停止执行,等待回收工作的完成。

  4、标记-压缩:指在回收时标记出所有的待回收的空间,然后通过复制的方式,将所有的分配空间转移到一端。

  5、标记-清除:指标记出待回收的空间后直接清理掉。

  6、复制式:即将可用内存空间一分为二,每次只使用其中的一份内存空间,在垃圾回收时,将内存中的可达对象全部复制到另外的一个空间,然后对本空间进行一次性回收。

  JVM在堆内存中采用的是分代回收的策略,这种策略是上述回收算法和方式的一个组合,JVM将内存分为新生代、老生代以及永久代的堆。

  年轻代中有三个区,分别是一个Eden区和两个Survivor区。新生成的对象是放在Eden区中,当Eden区满时,将Eden区中存活的对象复制到其中的一个Survivor区中,当这个Survivour区满了,则将存活的对象复制到另外一个Survivor区中,当另外一个区也满时,则会将其中存活的对象转移到老生代区中。

  老生代区中存放的是一些生命周期较长的对象。

  最后永久代中存放的是一些静态文件。

  JVM中垃圾回收机制在下列几种情况下触发:

  1、Eden区满,则会触发Scavenge GC,这个回收只会影响到新生代区,不会影响到其他区。

  2、当永久代、老生代满或者显示调用System.gc()时,会触发Full GC,这个效率比较低,要尽量避免。

时间: 2024-12-26 07:11:42

Java之内存回收的相关文章

关于仿照java的内存回收机制实现C++的自动内存回收的一点想法

java的内存回收机制是很高效的,对软件产生的额外影响很小.而在C++中的大多数智能指针都是采用的引用计数的策略实现,当计数到0时,将所指向的指针删除.这种智能指针当应用到比较大的对象或者动态内存分配的次数非常少时.对软件的性能不会有多大的影响,反而提高了对内存的使用效率.可是一旦使用动态内存分配的次数非常巨大的时候.不仅对内存的使用效率下降,软件的运行效率也会下降很多.这主要是因为,动态分配造成的存储碎片化使可用内存减少,cache命中率也会下降.对软件性能可能会造成几百倍的损失. 目前的想法

Java的内存回收

一.java引用的种类 1.对象在内存中的状态 可达状态:当一个对象被创建后,有一个以上的引用变量指向它. 可恢复状态: 不可达状态:当对象的所有关联被切断,且系统调用所有对象的finalize方法依然没有使该对象变成可达状态,那该对象将永久性的失去所有引用,最后变成不可达状态. 2.引用的类型 强引用: 软引用: 弱引用: 虚引用: 二.java的内存泄露 三.垃圾回收机制 1.垃圾回收算法 串行(Serial)回收和并行(Parallel)回收:串行是始终只有一个CPU在执行垃圾回收操作:并

Java的内存回收机制

在Java中,它的内存管理包括两方面:内存分配(创建Java对象的时候)和内存回收,这两方面工作都是由JVM自动完成的,降低了Java程序员的学习难度,避免了像C/C++直接操作内存的危险.但是,也正因为内存管理完全由JVM负责,所以也使Java很多程序员不再关心内存分配,导致很多程序低效,耗内存.因此就有了Java程序员到最后应该去了解JVM,才能写出更高效,充分利用有限的内存的程序. 1.Java在内存中的状态 首先我们先写一个代码为例子: Person.java 1 2 3 4 5 6 7

Java的内存回收机制详解

http://blog.csdn.net/mengern/article/details/38150431 Java中提供了垃圾强制回收机制的方法System.gc(),但是系统并不保证会立即进行垃圾回收,而是JVM根据定义的一套垃圾回收算法来确定,算法用来提高垃圾回收的效率. 判断一个存储单元是否是垃圾的依据是:该存储单元所对应的对象是否仍被程序所用,即是否有引用指向该对象.Java的垃圾回收器自动扫描对象的动态内存区,对所引用的对象加标记,然后把没有引用的对象作为垃圾收集起来并释放出去. J

No.4 Java的内存回收(内存回收)

1. Java引用的种类 内存管理分为:内存分配和内存回收.都是由JVM自动处理的 对象在内存中的状态:可达.可恢复(回收前调用finalize方法).不可达 JVM回收标准:是否还有引用变量引用该对象 有向图理解.线程对象作为根节点,变量.对象作为节点,引用关系作为有向边.在有向图中,从线程节点<当然线程对象也要存在,没有被销毁>可达的对象都是可达状态. 强引用 一般的引用/大部分 都是强引用,被强引用的对象不会被回收,是内存泄露的主要原因之一. 软引用 通过SoftReference类实现

[java,2017-05-15] 内存回收 (流程、时间、对象、相关算法)

内存回收的流程 java的垃圾回收分为三个区域新生代.老年代. 永久代 一个对象实例化时 先去看伊甸园有没有足够的空间:如果有 不进行垃圾回收 ,对象直接在伊甸园存储:如果伊甸园内存已满,会进行一次minor gc:然后再进行判断伊甸园中的内存是否足够:如果不足 则去看存活区的内存是否足够:如果内存足够,把伊甸园部分活跃对象保存在存活区,然后把对象保存在伊甸园:如果内存不足,向老年代发送请求,查询老年代的内存是否足够:如果老年代内存足够,将部分存活区的活跃对象存入老年代.然后把伊甸园的活跃对象放

android 内存回收

昨天朋友问我,如果一个java局部对象在调用jni的时候,如果java层没有引用它,这个对象会不会因为被jni层引用不被GC,导致内存泄漏.我大概想了一下,说不会.当时想的很简单,c里面没有像java一样的类似的内存回收机制,java层进入jni时值传递,不会导致引用产生.实事上比想象的复杂的多,而且并不是这样的. 按照这种想法,如果java层的对象被jni引用时不会计数,对象被GC时,jni层会产生野指针.事实并不是这样. 首先GC是发生在进程范围内的堆空间,如果堆里的对象没有被引用,是要被G

Java内存回收机制

深入理解 Java 垃圾回收机制 一:垃圾回收机制的意义 java  语言中一个显著的特点就是引入了java回收机制,是c++程序员最头疼的内存管理的问题迎刃而解,它使得java程序员在编写程序的时候不在考虑内存管理.由于有个垃圾回收机制,java中的额对象不在有"作用域"的概念,只有对象的引用才有"作用域".垃圾回收可以有效的防止内存泄露,有效的使用空闲的内存: 内存泄露:指该内存空间使用完毕后未回收,在不涉及复杂数据结构的一般情况下,java的内存泄露表现为一个

Java中内存空间的分配及回收

Java中内存分为: 栈:存放简单数据类型变量(值和变量名都存在栈中),存放引用数据类型的变量名以及它所指向的实例的首地址. 堆:存放引用数据类型的实例. Java的垃圾回收: 由一个后台线程GC(Garbage Collection)进行垃圾回收,虚拟机判定内存不够的时候会中断代码的运行,这个时候GC才进行垃圾回收. 缺点:不能够精确的去回收内存. java.lang.System.gc(); 上面代码会建议系统回收内存,但系统不一定回应,会先去看内存是否够用,够用则不予理睬,不够用才会去进行