zoukankan      html  css  js  c++  java
  • JVM·垃圾收集器与内存分配策略之对象是否可被回收!

    1、判断对象已经死去/不再被引用。
        1.1、引用计数算法:给对象添加引用计数器,有个地方引用就+1,引用失效就-1。任何时刻,引用为0,即判断对象死亡。
            1.1.1、优点:实现简单,效率高。
            1.1.2、缺点:在主流的Java虚拟机中不被使用,因为很难解决对象之间相互循环引用的问题。
        1.2、可达性分析算法(Java,C#,lisp):从一系列称为“GC Roots”的对象作为起始点,从这些节点往下搜索,搜索走过的路径称为引用链,当没有引用链可达到某对象时,认为该对象不可到达,即此对象没有被有效引用。
            1.2.1:可做为GC Roots的对象:
                        虚拟机栈中引用的对象
                        方法区中类静态属性引用的对象
                        方法区中常量引用的对象
                        本地方法栈中JNI(Native方法)应用的对象
     
    2、如何判断是否要被回收
        在Java中,采用可达性分析算法。即使判断未不可达的对象,也不会立即宣告对象死亡。在此之前要经过至少两次标记:
        2.1、第一次标记和筛选:当第一次判断该对象不可达(没有与GC Roots相连的引用链)时,进行筛选:是否要执行finalize()方法。
        2.2、第二次:需要finalize()方法的对象会在一个低优先级的F-Queue中排队执行finalize()。如果在finalize()方法中拯救自己,那么就不会死。否则,被回收。
                在finalize()方法中拯救自己:在改方法中重新连接上GC Roots(重新拥有连接GC Roots的引用)
        2.3、总结:对象可以在被GC时自我拯救。这种拯救只有一次机会,因为GC只会调用一次对象的finalize()方法。
                附自我拯救代码:
    **
    * Created by KEY on 2017/12/4.
    */
    public class FinalizeEscapeGC {
        public static FinalizeEscapeGC SAVA_HOOK = null;
    
        public void isAlive(){
            System.out.println("yes, I am still alive");
            }
        @Override
        protected void finalize() throws Throwable{
            super.finalize();
            System.out.println("finalize method executed");
            FinalizeEscapeGC.SAVA_HOOK = this;
        }
    
        public static void main(String[] args) throws Throwable{
            SAVA_HOOK = new FinalizeEscapeGC();
    
            //对象第一次拯救自己
            SAVA_HOOK = null;
            System.gc();
            //因为finalize优先级很低,所以等他0.5s
            Thread.sleep(500);
            if(SAVA_HOOK != null){
                SAVA_HOOK.isAlive();
            }else{
                System.out.println("no,I am dead :(");
            }
    
            //重复以上代码,看是否能第二次拯救自己
            //对象第一次拯救自己
            SAVA_HOOK = null;
            System.gc();
            //因为finalize优先级很低,所以等他0.5s
            Thread.sleep(500);
            if(SAVA_HOOK != null){
                SAVA_HOOK.isAlive();
            }else{
                System.out.println("no,I am dead :(");
            }
        }
    }
    

      

    3、方法区的垃圾回收
        说明:虚拟机规范对于方法区的实现并没有要求是否回收,也没有要求如何回收,甚至没有要求具体的内存定义, 只需要满足方法区规范即可。所以方法区的回收再不同的虚拟机有不同的实现
        方法区的回收主要针对“废弃常量”和“无用的类”。如何判断是否是“无用的类”
        a.该类所有的实例都已经被回
        b.加载该类的ClassLoader被回收
        c.该类对应的java.lang.class对象没有在任何地方被引用,无法再任何地方通过反射访问该类的方法。
    凡你能说的,你说清楚。凡你不能说的,留给沉默!
  • 相关阅读:
    Spring Cloud Gateway 使用
    Spring Cloud Stream 整合 RabbitMQ
    机器学习知识总结---1、回归和分类是可以相互转换的
    23个适合Java开发者的大数据工具和框架
    serilog Getting Started
    NLog.Targets.ElasticSearch
    RollingFileAppender bufferSize is not working? Here is an alternative
    go微服务示例(k8s istio grpc swagger postgres增量更新sql等功能)
    undefined: grpc.SupportPackageIsVersion6 和 undefined: grpc.ClientConnInterface 解决办法
    micrometer埋点(Spring boot 2.X metrics)
  • 原文地址:https://www.cnblogs.com/dhcao/p/10452065.html
Copyright © 2011-2022 走看看