java模拟JVM的GCRoots追踪算法,对象可达性分析

Posted csldm

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java模拟JVM的GCRoots追踪算法,对象可达性分析相关的知识,希望对你有一定的参考价值。

package com.yh.stu.jvm.garbage;

import java.util.*;

/**
 * 实现一个GCRoots算法
 *
 * @author DSH
 * @create 2019-08-05-15:17
 */
public class GCRootsTest 
    private static TraceTable traceTable = new TraceTable();
    private static StackFrame stackFrame = new StackFrame();
    private static Generation newGeneration = new Generation();
    private static Generation oldGeneration = new Generation();

    public static void main(String[] args) 
        /**
         * 在年轻代放入10000个对象 ,存活100个
         */
        final int totalNewObjAmt = 10_000;
        for (int i = 0; i < totalNewObjAmt; i++) 
            ObjectStorageStructure objSt = new ObjectStorageStructure("#A000-"+i, "A000"+i);
            newGeneration.add(objSt);
        
        /**
         * 在老年代代放入10000个对象 ,存活9900个
         */
        final int totalOldObjAmt = 10_000;
        for (int i = 0; i < totalOldObjAmt; i++) 
            ObjectStorageStructure objSt = new ObjectStorageStructure("#B000-"+i, "A000"+i);
            oldGeneration.add(objSt);
        


        createRealation(newGeneration, 10);
        createRealation(oldGeneration, 990);
        System.out.print("Minor gc cost:");
        newGeneration.gc();
        System.out.println("==================================================");
        System.out.print("Major gc cost:");
        oldGeneration.gc();


    

    /**
     * 随机建立对象的引用关系
     */
    private static void createRealation(Generation generation, int childrenPerObj) 
        for (int i = 0; i < 10; i++) 
            ObjectStorageStructure objStRoot = getRandomObjFromGen(generation);
            stackFrame.addAddr(objStRoot.addr);
            for (int j = 0; j < childrenPerObj; j++) 
                ObjectStorageStructure objStChild = getRandomObjFromGen(generation);
                objStRoot.addRefObj(objStChild);
                addTraceTable(objStRoot, objStChild);
            
        
    

    private static void addTraceTable(ObjectStorageStructure objStRoot, ObjectStorageStructure objStChild) 
        List<String> headList = traceTable.headMap.get(objStRoot.addr);
        if (headList == null) 
            headList = new ArrayList<>();
        
        headList.add(objStChild.addr);
        traceTable.headMap.put(objStRoot.addr, headList);
    

    private static ObjectStorageStructure getRandomObjFromGen(Generation generation) 
        Random random = new Random();
        List<ObjectStorageStructure> objStList = generation.getObjStList();
        int randomIndex = random.nextInt(objStList.size());
        ObjectStorageStructure objSt = objStList.get(randomIndex);
        return objSt;
    

    public static String getUUID() 
        return UUID.randomUUID().toString();
    

    private static void execute() 
        stackFrame.addAddr(UUID.randomUUID().toString());
    

    static class Generation 
        private List<ObjectStorageStructure> objStList = new ArrayList<>();
        private Map<String, ObjectStorageStructure> map = new HashMap<>();

        public void gc() 
            TimerTools timerTools = new TimerTools();
            timerTools.start();
            //复制对象,这里用sleep(1)表示复制的时间消耗
            int i = 1;
            for (String rootAddr : stackFrame.getVarAddrList()) 
                List<String> addrList = traceTable.headMap.get(rootAddr);
                for (String childAddr : addrList) 
                    if (map.get(childAddr) != null) 
                        try 
                            Thread.sleep(0,0);
                         catch (InterruptedException e) 
                            e.printStackTrace();
                        
                        System.out.println((i++) + "-" + map.get(childAddr));
                    
                
            
            System.out.println(timerTools.spent());
        

        public void add(ObjectStorageStructure objSt) 
            this.objStList.add(objSt);
            this.map.put(objSt.addr, objSt);
        

        public List<ObjectStorageStructure> getObjStList() 
            return objStList;
        
    

    static class TraceTable 
        private Map<String, List<String>> headMap = new HashMap();
    

    static class StackFrame 
        private List<String> varAddrList = new ArrayList<>();//存放对象引用地址

        /**
         * 在栈帧中放入对象引用地址
         *
         * @param addr
         */
        public void addAddr(String addr) 
            this.varAddrList.add(addr);
        

        public List<String> getVarAddrList() 
            return varAddrList;
        
    

    static class ObjectStorageStructure 
        private String addr;
        private Object obj;
        private List<ObjectStorageStructure> refObjList = new ArrayList<>();//引用对象

        public ObjectStorageStructure(String addr, Object obj) 
            this.addr = addr;
            this.obj = obj;
        

        public void addRefObj(ObjectStorageStructure objSt) 
            refObjList.add(objSt);
        

        @Override
        public String toString() 
            return "ObjectStorageStructure" +
                    "addr=‘" + addr + ‘\‘‘ +
                    ", obj=" + obj +
                    ‘‘;
        
    


  

以上是关于java模拟JVM的GCRoots追踪算法,对象可达性分析的主要内容,如果未能解决你的问题,请参考以下文章

JVM垃圾收集

JVM垃圾回收 GC

JVM(二) GC算法与分代回收策略

JVM理论:(二/2)判断对象是否已死

JVM对象已死

JVM垃圾收集器与内存分配策略