• jvm几种垃圾回收机制小结


    1.引用计数算法

    引用计数(Reference Counting)算法是每个对象计算指向它的指针的数量,当有一个指针指向自己时计数值加1;当删除一个指向自己的指针时,计数值减1,如果计数值减为0,说明已经不存在指向该对象的指针了,所以它可以被安全的销毁了。

    引用计数的明显缺点:无法处理环形引用

    算法特点

    1. 需要单独的字段存储计数器,增加了存储空间的开销;

    2. 每次赋值都需要更新计数器,增加了时间开销;

    3. 垃圾对象便于辨识,只要计数器为0,就可作为垃圾回收;

    4. 及时回收垃圾,没有延迟性;

    5. 不能解决循环引用的问题;

    2. 标记-清除(Mark-Sweep)算法

    例如: Lua就采用了mark-sweep的垃圾回收机制

    标记-清除(Mark-Sweep)算法依赖于对所有存活对象进行一次全局遍历来确定哪些对象可以回收,遍历的过程从根出发,找到所有可达对象,除此之外,其它不可达的对象就是垃圾对象,可被回收。整个过程分为两个阶段:标记阶段找到所有存活对象;清除阶段清除所有垃圾对象。

     

    优点

    • 相比较引用计数算法,标记-清除算法可以非常自然的处理环形引用问题,

    • 另外在创建对象和销毁对象时时少了操作引用计数值的开销

    缺点

    • 标记-清除算法是一种“停止-启动”算法,在垃圾回收器运行过程中,应用程序必须暂时停止

    • 标记-清除算法在标记阶段需要遍历所有的存活对象,会造成一定的开销

    • 在清除阶段,清除垃圾对象后会造成大量的内存碎片。

    3. 标记-缩并(Mark-Compact)算法(解决内存碎片)

    整个过程可以描述为

    • 标记所有的存活对象;
    • 通过重新调整存活对象位置来缩并对象图;
    • 更新指向被移动了位置的对象的指针。

    标记-压缩算法最大的难点在于如何选择所使用的压缩算法,如果压缩算法选择不好,将会导致极大的程序性能问题,如导致Cache命中率低等。一般来说,根据压缩后对象的位置不同,压缩算法可以分为以下三种:

    1. 任意:移动对象时不考虑它们原来的次序,也不考虑它们之间是否有互相引用的关系。

    2. 线性:尽可能的将原来的对象和它所指向的对象放在相邻位置上,这样可以达到更好的空间局部性。

    3. 滑动:将对象“滑动”到堆的一端,把存活对象之间的自由单元“挤出去”,从而维持了分配时的原始次序。

    4. 4. 节点拷贝(Copying)算法(解决内部碎片)

      节点拷贝算法是把整个堆分成两个半区(From,To), GC的过程其实就是把存活对象从一个半区From拷贝到另外一个半区To的过程,而在下一次回收时,两个半区再互换角色。在移动结束后,再更新对象的指针引用

      参考
      http://blog.csdn.net/sinat_36246371/article/details/53002209

     简单,高效,空间换时间。

    5 Generational Collection(分代收集)算法

    分代收集算法是目前大部分JVM的垃圾收集器采用的算法。它的核心思想是根据对象存活的生命周期将内存划分为若干个不同的区域。一般情况下将堆区划分为老年代(Tenured Generation)和新生代(Young Generation),老年代的特点是每次垃圾收集时只有少量对象需要被回收,而新生代的特点是每次垃圾回收时都有大量的对象需要被回收,那么就可以根据不同代的特点采取最适合的收集算法。

    目前大部分垃圾收集器对于新生代都采取Copying算法,因为新生代中每次垃圾回收都要回收大部分对象,也就是说需要复制的操作次数较少,但是实际中并不是按照1:1的比例来划分新生代的空间的,一般来说是将新生代划分为一块较大的Eden空间和两块较小的Survivor空间,每次使用Eden空间和其中的一块Survivor空间,当进行回收时,将Eden和Survivor中还存活的对象复制到另一块Survivor空间中,然后清理掉Eden和刚才使用过的Survivor空间。

    而由于老年代的特点是每次回收都只回收少量对象,一般使用的是Mark-Compact算法。

    注意,在堆区之外还有一个代就是永久代(Permanet Generation),它用来存储class类、常量、方法描述等。对永久代的回收主要回收两部分内容:废弃常量和无用的类。

    原文:https://doctording.blog.csdn.net/article/details/53728388?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control&dist_request_id=6b460756-003e-4553-a15f-de282251b1c3&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-1.control


    6、JVM不同的版本垃圾回收机制不一样,jdk1.7和1.8新版本和老版本区别


    jdk1.7和1.8旧版本Parallel Old,(老年代)
    jdk1.7和1.8新版本Parallel Scavenge,(新生代)

    Parallel Old 收集器
    Parallel Scavenge收集器的老年代版,使用多线程与标记–整理算法。这个收集器在jdk1.6中才开始提供的,直到Parallel Old 收集器出现后,“吞吐量优先”收集器终于有了比较名副其实的应用组合,在注重吞吐量以及CPU资源敏感的场合,都可以优先考虑Parallel Scavenge加 Parallel Old收集器

    Parallel Scavenge收集器
    Parallel Scavenge收集器是一个新生代的手机器,使用的是复制算法的收集器,而且也是多线程的收集器。。Parallel Scavenge收集器,目标达到一个可控制的吞吐量,使用-XX:MaxGCPauseMillus参数控制垃圾停顿时间,使用-XX:GCTimeRatio参数控制吞吐量。Parallel Scavenge收集器设置-XX:UseAdaptiveSizePolicy参数,虚拟机会根据当前系统的运行情况收集性能监控信息,动态调整这些参数以提供最合适的停顿时间或者最大吞吐量(GC自使用的调节策略)。
    自适应调节策略也是Parallel Scavenge收集器和ParNew收集器一个重要的区别。

    7 、需要了解


    1、GC 是什么? 为什么要有GC
    GC 是垃圾收集的意思,内存处理是程序员人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java 提供的GC 功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java 语言没有提供释放已分配内存的显示操作方法。Java 程序员不用担心内存管理,因为垃圾收集器会自动进行管理。要请求垃圾收集,可以调用下面的方法之一:
    System.gc() 或Runtime.getRuntime().gc()


    2、垃圾回收器的基本原理是什么
    对于GC 来说,当程序员创建对象时,GC 就开始监控这个对象的地址、大小以及使用情况。通常,GC 采用有向图的方式记录和管理堆(heap)中的所有对象。通过这种方式确定哪些对象是"可达的",哪些对象是"不可达的"。当GC 确定一些对象为"不可达"时,GC 就有责任回收这些内存空间。


    3、有什么办法主动提醒虚拟机进行垃圾回收器回收垃圾吗
    可以,可以手动执行System.gc() 或 Runtime.getRuntime().gc(),通知GC 运行,但是Java 语言规范并不保证GC 一定会执行。


    4、垃圾回收机制回收的是什么
    垃圾回收机制的目标是回收无用对象的内存空间(记住:不是对象),这些内存空间是JVM堆内存的内存空间。垃圾回收只回收内存资源,对于那些物理资源,如数据库连接,Socket,I/O流等资源无能无能为力,我们要自己关闭回收。

    原文链接:https://blog.csdn.net/weixin_43122090/article/details/103652073

  • 相关阅读:
    洛谷 P3146 [USACO16OPEN]248
    洛谷 P2633 Count on a tree
    bzoj 1040 1040: [ZJOI2008]骑士
    poj 3417 Network
    洛谷 P2149 [SDOI2009]Elaxia的路线
    2、小文件问题解决
    ☀【组件
    -_-#【JS】隐含全局变量
    -_-#flash播放器自适应
    -_-#【插件】MD5
  • 原文地址:https://www.cnblogs.com/lshan/p/14462946.html
Copyright © 2020-2023  润新知