常见面试题之jvm内存回收和分配策略

  • 如何判断对象可回收

    根据可达性分析算法来判断一个对象是否可回收,可达则不可回收,否则可回收;
    从GC Roots对象开始,有引用链,存活,没有则可回收,属于GC Roots类型对象如下:
    1.方法中的 参数,局部变量,临时变量 (关心---堆区回收)
    2.静态变量(关心---方法区回收)
    3.字符串常量的引用 (关心---方法区回收)
    4.本地方法(native JNI)引用的对象
    5.被同步锁持有的对象 (关心---堆区回收)
    
    class Test{
          
          
    	//静态变量
        private static Object c=new Object();
        
        public void test(参数){
          
          
        //局部变量,临时变量
        Object o=new Object();
        }
    }
    说明:
    1.回收不仅仅是针对堆区,回收会分为方法区回收和堆区回收
    2.堆区回收一些对象
    3.方法区回收字符串常量和类型信息和静态变量
    
  • 引用类型

    强引用: 尽管发送oom,也不回收的对象
    软引用:内存不足情况下,会回收弱引用对象,内存依然不足,发生oom
    弱引用:不管内存是否足够,下一次发生GC都会回收调的对象
    虚引用:忽略
    
  • 分代收集算法(针对堆回收)

    1.分代收集理论:实际开发当中,对象分为两种:绝大部分对象朝生夕死,少部分对象存活比较长。
    		基于这个理论,对堆划分代,不同代采用不同回收策略,那就是不同代使用不同回收算法,
    		最大的提高了回收效率。
    2.分代回收类型:
     新生代收集:Minor GC (堆分区的年轻代)
     老年代收集:Major GC (堆老年代)
     混合收集:Mixed GC (堆新生代和部分老年代)
     整堆收集:Full GC (整个堆和整个方法区)
    
    3.基本回收算法
      标记清除算法:在堆中标记出非存活对象,然后释放掉;在堆中标记出存活对象,把剩下的释放掉,可选择的。
      			 缺点:1.效率不稳定,看存活对象的多少,就要标记多少,内存大的情况下,效率极低
      			 	  2.碎片化内存,就原地释放,释放完后内存不一定连续
      			 	  
      标记复制算法:年轻代对象98%活不过第一轮垃圾回收,也就是98%的对象都是要回收的,把年轻代的堆内存
      			 分为两半,每次只用一块内存,垃圾回收时,直接把存活对象复制到另外一半内存,按顺序
      			 进行分配剩下存活的对象
      			 优点:1.不存在内存碎片化的问题,效率也高
      			 缺点:1.比较浪费内存(后面进行了优化,将年轻代划分为eden和两个survivor,内存比例
      			 为811,也就是每次只会浪费10%的内存)
      			 总结:年轻代对象的特点,大多数选用这种垃圾回收算法
      			 
      标记整理算法: 将内存中存活的对象,直接移向内存的另外一端,然后擦除边界以外的部分
      			  优点:1.不存在碎片化问题相对标记清除算法
      			  	   2.不需要浪费10%的额外空间相对于标记复制算法
      		
      总结:1.年轻代的特性,标记复制算法比较适合
      	   2.老年代的特性,标记清算和标记整理算法比较适合;标记清除由于碎片化问题,分配内存成本较高
      	     标记整理不存在碎片化问题,但是要移动内存,分配内存方便,但是移动内存成本高
      			 
    
  • 常见分代垃圾收集器

    年轻代:
    	serial: 使用标记复制算法,gc线程与应用线程是串行化的,gc时候所有应用线程暂停,直到gc完成
    	        (适合内存比较小的情况下,如果再内存大的情况下,gc停顿太长,很影响用户体验)
    	parNew: 使用标记复制算法,gc线程与应用线程是串行化的,gc时候所有应用线程暂停,直到gc完成
    			但是这个是serial的多线程版本,多个gc线程进行工作
    			(适合内存比较大的情况下,因为gc多个线程工作,回收快,停顿时间短)
    	parallel Scavenge:使用标记复制算法,gc线程与应用线程是串行化的,gc时候所有应用线程暂停,直到gc完成
    			但是这个是serial的多线程版本,多个gc线程进行工作
    			(和parNew差不多,但是可以根据业务场景,可调整gc时间,让吞吐量达到一定可控)
    老年代:
    	serial old:使用标记整理算法,gc线程与应用线程是串行化的,gc时候所有应用线程暂停,直到gc完成
    	parallel old:使用标记整理算法,gc线程与应用线程是串行化的,gc时候所有应用线程暂停,直到gc完成
    				 但是这个是serial old的多线程版本,多个gc线程进行工作
    	cms:使用标记清除算法,gc线程可以和用户线程并行,停顿时间短
    
  • JDK8默认垃圾收集器

    设置jvm options:-XX:+PrintGCDetails -XX:+PrintGCTimeStamps
    
    Heap
     PSYoungGen      total 76288K, used 5261K [0x000000076ab00000, 0x0000000770000000, 0x00000007c0000000)
      eden space 65536K, 8% used [0x000000076ab00000,0x000000076b0234a8,0x000000076eb00000)
      from space 10752K, 0% used [0x000000076f580000,0x000000076f580000,0x0000000770000000)
      to   space 10752K, 0% used [0x000000076eb00000,0x000000076eb00000,0x000000076f580000)
     ParOldGen       total 175104K, used 0K [0x00000006c0000000, 0x00000006cab00000, 0x000000076ab00000)
      object space 175104K, 0% used [0x00000006c0000000,0x00000006c0000000,0x00000006cab00000)
     Metaspace       used 2934K, capacity 4496K, committed 4864K, reserved 1056768K
      class space    used 319K, capacity 388K, committed 512K, reserved 1048576K
    
    总结:jdk8的情况下,使用的垃圾回收parallel Scavenge 和parallel old
    
  • 内存分配策略(jdk默认 PSYoungGen ParOldGen)

     1.优先分配到eden区,如果内存不够,发生minor gc,存活对象超过survivor大小,多出的直接转移到老年代
       否则,交换到survivor,将空出来的eden内存分配给新进来的对象
     2.大对象直接分配到老年代(-XX:PretenureSizeThreshold)
     3. 根据对象的年龄进入老年代(-XX:MaxTenuringThreshold)
     
     分配小例子:
     代码:
     //-Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:PretenureSizeThreshold=6291456
      byte[] b1=new byte[_1M*4];
      byte[] b2=new byte[_1M*2];
       
    gc日志分析:
     	1.一开始占用2596k
       2.创建了一个数组用了 4096 --->已经使用6692k,eden剩余,1500k
       3.创建一个数组用了 2048---->eden需要内存6692+2048,明显eden内存不够,发生minor gc一次
                             ----->发现survivor只有1024k,而总存活对象为6692k(担保分配到老年代4104k,		survivor分配840k,回收了1584k,eden区留了163k)
                            ----->2048k对象经过gc就可以直接分配到eden了 
    

    gc日志
    在这里插入图片描述

  • jvm内存模型

    
    

猜你喜欢

转载自blog.csdn.net/weixin_38312719/article/details/106799188