zoukankan      html  css  js  c++  java
  • GC

    为减轻GC压力,我们需要注意些什么?

    软件如何设计架构
    代码如何写
    堆空间如何分配(不要把对内存-xmx,-xms调的太大,gc时间长)
    像小对象不要太多啊,容易经常产生碎片要碎片整理(比如可以对象池啊啥的重用)
    大对象不要太大啊,gc时间太长(分页、分块啥的)

    gc的时候会查看对象是否被jvm调用过finalize(),如果把这个对象丢到一个finalizer的队列里,由finalizer终结器线程处理对象内存释放前的一些自定义的结束操作
    把它加入到队列的时候,这时会标记已经被加入到finalizer队列里了,以后就不会加入了,就算被复活了,但是自己调用finalize(),不会标记这个,不影响,所以gc的时候只会执行一次finalize()方法
    gc和finalizer不同线程,另外gc可以并行收集,不同线程因为怕无限等待finalize(),jvm崩掉
    然而这个线程的优先级较低,可能第二次gc都开始了,所以并不保证finalizer会调用在前,或者被调用
    所以像socket,conn,reader,file这种非内存资源东西的关闭,最好不止写在重载的finalize()方法里,可以try{}catch{}finally{},在finally里面关闭掉
    在gc的时候发现对象已经标记过加入finalizer队列的就会直接释放内存完成清理了
    在finalize里可能会复活对象,可能重新附上引用,那么就又是可达的了,就不会被gc清理了,但是因为gc只会调用一次finalize,所以,不手动是不会复活两次的

    Java中可以作为GC ROOT的对象有:
    静态变量引用的对象
    常量引用的对象
    本地方法栈(JNI)引用的对象
    Java栈中引用的对象

    可达可触及:
    可触及的–从GC ROOT这个根节点对象,沿着引用的链条,可以触及到这个对象,该对象就叫可触及的,也就是之前说的可达性算法的思想。
    可复活的–一旦所有引用被释放,就是可复活状态,因为在finalize()中可能复活该对象(finalize方法只会调用一次)。
    不可触及的–在finalize()后,可能会进入不可触及状态,不可触及的对象不可能复活,就可以回收了。

    finalize()在什么时候被调用?
    有三种情况:
    所有对象被Garbage Collection时自动调用,比如运行System.gc()的时候。
    程序退出时为每个对象调用一次finalize方法。
    显式的调用finalize方法。

    java没用引用计数法,要加减引用消耗不小,或者怕出现循环引用,没用的释放不掉

    jvm的垃圾回收器有很多种,比如并行收集器,串行收集器,与用户线程一起执行的停顿短暂的并行收集器
    其中有可能
    java采用的是标记清楚对新生代或者复制算法(比较快,费一般内存),标记压缩清楚对老年代(节省空间)

    gc的时候会stop-the-world,因为会怕新的对象产生,引用变化或新垃圾产生,还有压缩或者碎片整理可能会移动内存,会停在暂停点,没在的可能会被线程劫持,停在暂停点
    其它的stop-the-world可能是由于程序员获取snapshot,dump,或者jvm死锁检测引起的
    这是Java中一种全局暂停的现象,全局停顿,所有Java代码停止,类似JVM挂起的状态……但是native代码可以执行,但不能和JVM交互

    强引用会让gc-root对象可达
    弱引用,如果没有强引用了,立刻可以被gc回收
    软饮用,如果没有强引用,会在没内存的时候jvm调用gc回收,可以用来做缓存
    虚引用,没什么实际用,标记可以被回收了

  • 相关阅读:
    Git远程操作
    696. Count Binary Substrings
    693. Binary Number with Alternating Bits
    821. Shortest Distance to a Character
    345. Reverse Vowels of a String
    89. Gray Code
    数组操作符重载
    C++字符串反转
    马克思的两面性-来自网友
    C++字符串
  • 原文地址:https://www.cnblogs.com/HaibaraAi/p/6535705.html
Copyright © 2011-2022 走看看