Java内存管理

                                      Java内存管理

      学过几年Java的同学肯定都非常关心Java的内存管理,Java内存管理具有一定的自动化能力,不能C++那样申请的内存需要主动释放,Java释放内存是通知垃圾收集器回收的,垃圾收集器是JVM的一个后台线程,也不一定就是一个线程,现在的CMS和G1收集器可以实现并发的垃圾回收了。Java内存的自动管理像个围城,城外的人想进来,城里的人想出来。无数的C++大神和Java程序员吐槽过Java的内存自动管理,因为C++想要释放一块内存只需要delete一下就好了,Java虽然可以调用System.gc()方法来提醒JVM回收,但也只是提醒而已,JVM到底回不回收,啥时候回收,就要看JVM的"心情"了。

      Java的一大特性就是Java内存的自动管理,虽然无数人吐槽,但是确实让无数程序员和无数的Java项目获益许多,可以说,Java在编程语言使用量独占鳌头这么多年Java内存自动管理占了很大功劳。使用过C++的程序员肯定都知道delete关键词,delete可以释放一块内存,但Java不能主动释放内存。Java的JVM本身带有一系列的垃圾收集器,为了一些效率问题,JVM还把Java的内存分成了几个逻辑区域,不同的对象放入不同的区域。

      首先是JVM的几个常见的回收算法,最简单的就是标记-清除算法。标记-清除算法有两个阶段,一个是标记过程,标记过程就是给每个需要回收的对象添加一个标志,这个标记算法通常有引用计数器和可达性分析两种算法,但现在的JVM大都采用后者。给所有需要回收的对象都添加上标志之后就统一清除。标记-清除算法的缺点很明显,就是效率不高和内存碎片多。

      由于标记-清除算法会产生很多内存碎片,所以复制算法在标记-清除算法的基础上进行了改良,通过牺牲一些复制的效率来提高内存利用率。复制算法和标记-清除基本一样,只是需要把还存活的对象复制到另外的地方去,一般是把总的内存对半分割,分配的内存在一边,另一边是先前还存活的对象,一次回收时,先把还存活的对象复制到另一边,再统一清除"死亡"的对象。这样就不会产生内存碎片了,但缺点依然很明显,就是复制算法对内存的利用率只有50%,而且复制会非常浪费效率。虽然说复制算法效率也不高,但商业的JVM新生代内的对象大多采用复制算法来回收,因为新生代中的对象大多是一些"朝生暮死"的对象,这些对象基本上都是要被回收的,因此复制浪费的效率并不多,而且这样也不需要把内存对半分割了,因为只有一小部分的对象能够存活下来。

      还有一种叫做标记-整理算法的来解决标记-清除算法缺点的。标记-整理算法是把存活的对象移动到内存的一端,然后清除边界以外的内存。根据对象的不同特性,可以将对象分为短生命和长生命两种类型,所以可以建立新生代内存区和老年代内存区,新生代用复制算法,老年代用标记-清除或者标记-整理算法。


    垃圾收集器大致可以分为两大类:单线程收集器和并发收集器。和普通的并发编程一样,单线程的优势就是执行简单,不需要上下文切换,效率较高,但不能充分利用多核CPU,每次进行垃圾回收时都需要暂停用户线程,在"Stop The World",如果每99ms回收一次,回收一次消耗1ms,那么效率就是99%,这在高并发的服务器中是不能被接受的,但如果每次回收只消耗0.01ms的话,在桌面程序中倒是还可以接受。多线程收集器就是可以并发地进行垃圾回收,充分利用了多核CPU的优势。但如果上下文切换频繁,就会非常浪费效率,这在Java并发编程中讲到过。

      Serial收集器就是一种单线程收集器,而ParNew收集器就是一个并发收集器,但其实只有CMS收集器才是真正意义上的并发收集器,CMS收集器才能真正的在执行用户线程时还可以进行垃圾回收。CMS收集器总的来说还是基于标记-清除算法的,包括了四个阶段,分别是初始标记,并发标记,重新标记,并发清除。CMS收集器的缺点就是因为是多线程的,会消耗一定的CPU时间片,会跟用户线程竞争一些系统资源,如果这种切换非常频繁,将会大大影响程序的性能。

      从JDK1.7开始出现了G1收集器,G1收集器的特点是并行并发、分代收集、空间整合、可预测停顿。G1把内存分为很多大小相等的Region区域,在回收内存时,通过比较这些Region的回收价值来确定回收方式,这里的回收价值通常用内存大小和回收时间来计量。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值