java中的垃圾回收机制

垃圾回收机制:

垃圾回收的主要作用是回收不在使用的内存。

在C/C++语言中,内存的分配与释放由开发人员自己决定。忘记或错误释放内存会导致程序不正常或者崩溃。java语言中引入垃圾回收机制,可以自动检测对象的作用域,把不再使用的存储空间释放掉。

垃圾回收器的意义:

1把开发人员从繁杂的释放内存的工作中解放出来,提高了效率。

2对开发人员屏蔽了释放内存的方法,避免开发人员操作错误导致程序崩溃,保证了程序的稳定性

垃圾回收的副作用:

垃圾回收机制中,垃圾回收器跟踪内存的使用情况,释放没用的对象,释放后还需要处理对象所在堆内存中的碎片,处理这些碎片必然增加JVM的负担,从而降低程序执行效率。

垃圾回收器三项任务:分配内存,回收不再引用的对象的内存空间,确保被引用对象的内存不被错误的回收。

垃圾回收原理:垃圾回收器使用有向图管理堆内存的所有对象,通过这个有向图可以识别哪些对象是“可达的”(有引用变量引用的就是可达的),哪些对象是“不可达的”(没有引用变量引用的就是不可达的),所有不可达的对象都可以被垃圾回收。也就是说,一个对象如果没有任何变量去引用它,那么该对象将不可能被程序访问,因此认为它是垃圾信息,可以被回收。只要有一个以上的变量引用该对象,该对象就不会被垃圾回收。

看下面的例子:

 

在这个例子中,main函数存在栈帧中,此栈中有两个变量,i1和i2,他们分别引用堆内存中的Integer对象1,2。当执行完i2=i1这句后,已经没有i2中此时保存Integer对象1的首地址,因此Integer 2对象已经没有引用变量引用了。也就是说Integer 2对象是不可达的了。因此Integer 2对象应该被垃圾回收。回收到Integer2对象占用的堆空间。

 

 

垃圾回收过程都是按照一定算法进行的,常见的有:

  1. 引用计数算法:堆中每个对象都有一个引用计数器,当有新的引用变量引用该对象,对象的引用计数器加一;当某个引用变量不在引用该对象,或者超过了某个引用变量的作用域,对象的引用计数器减一。这种方法无法解决一个问题,就是当对象中存在相互引用构成一个环的时候,这些对象都不在使用,但是无法回收。因此JVM舍弃了这种算法。
  2. 追踪回收算法:根据JVM维护的对象引用图,从根节点开始遍历这个对象引用图,遍历到某个对象就给它做个标记,遍历结束,没有被标记到的对象就是没有被引用的,可以被垃圾回收。
  3. 压缩回收算法:把堆中活动的对象移动到堆的一端,这样另一端就留出很大的空闲区域,相当于对碎片进行了处理。这种算法大大减少了消除碎片的工作,但是会带来性能损失。
  4. 复制回收算法:把堆分成大小相同的两块,任何时候只有一块在被使用,直到这块消耗完,垃圾回收期中断程序,遍历这块,把活动的对象复制到另一块,放置到另一块的时候他们是挨着放置的,因此消除了内存碎片。然后等这块消耗完,采用同样的方式继续。   这种算法优点:在垃圾回收的同时,对对象进行了新的布置,消除了内存碎片。 缺点:终端程序,降低了程序执行效率。对于指定堆,需要两倍大小的堆空间。
  5. 按代回收算法:将堆分成两个或者多个子堆,每个子堆视为一代,算法运行过程中优先收集“年幼”的对象,如果一个对象多次收集仍然“存活”,那么将这个对象转移到更高一级的堆里面,减少对它的扫描次数。 因为大部分对象的生命周期都很短,只有一部分对象生命周期较长。复制回收算法中每次复制全部活动对象的方法效率太低,因此才引入这种算法。

成为垃圾的对象,只有下次垃圾回收器运行时候才会被回收,不是马上被清理。

Java语言并没有提供显式释放已经分配内存的方法,开发人员不能实时调用垃圾回收器对某个对象或者所有对象进行垃圾回收。但是可以调用System.gc()方法来通知垃圾回收器回收。但是JVM并不保证垃圾回收器马上会运行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值