JVM进阶调优系列(3)堆内存的对象什么时候被回收?

简介: 堆对象的生命周期是咋样的?什么时候被回收,回收前又如何流转?具体又是被如何回收?今天重点讲对象GC,看完这篇就全都明白了。

上文末尾留了一道题给大家思考:堆对象的生命周期是咋样的?什么时候被回收,回收前又如何流转?具体又是被如何回收?今天重点讲对象GC,看完这篇就清晰了。

一、虚拟机栈会发生GC吗?

     上一篇文章说到虚拟机栈,虚拟机栈里有局部变量,这个局部变量引用了一个对象,这个对象在堆内存是要被GC回收的,但是虚拟机栈要不要做GC呢,不GC那这个局部变量怎么办?

     实际是不用GC的。线程的虚拟机栈,就是块单独的内存,和堆内存不在一起。虚拟机栈的局部变量,在出栈的时候,就从栈内存里移除去了,出栈完,这个栈内存就清空。所以不需要GC。


二、什么时候会发生YGC?

当JVM想把在年轻代里新增一个对象,但是年轻代空间不足,就会发生YGC。那年轻代空间为何不足呢,如何设置年轻代的大小。我们看一下JVM内存的核心参数。

-Xms:堆内存,最开始堆内存初始大小。

-Xmx:堆内存可以扩张到最大的大小。

-Xmn:堆内存里,年轻代占用的大小,堆内存大小-年轻代大小=就是老年代的空间大小。年轻代里上一篇文章说过里面分:Eden区、SurvivorTo区和SurvivorFrom区,他们按8:1:1的比例划分年轻代的空间。

-XX:MetaspaceSize:元数据空间大小,在JDK8之前对应的是永久代PermSize。

-XX:MaxPermSize:元数据空间可以扩张的最大大小,在JDK8之前对应的永久代MaxPermSize。

-Xss:每个线程虚拟机栈的大小。


所以当-Xmn年轻代里的Eden区空闲内存无法存放新对象,也就是空间不够,这时候就触发YGC,需要将部分对象回收,无法回收的挪到老年代腾出空间。


三、以下代码发生了YGC,哪些对象会被回收哪些不能回收?

package lading.java.jvm;
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
/**
 * 说说这个.class 加载到jvm经历的过程,以及在执行过程中,内存如何分配,GC的详细过程
 */
public class Demo002JvmShow {
    public static final String name = "我是类静态变量";
    public static User userA = new User("A");
    public static SoftReference<User> userB = new SoftReference<>(new User("B"));//软引用
    public static WeakReference<User> userC = new WeakReference<>(new User("C"));//弱引用
    public static PhantomReference<Object> objectD = new PhantomReference<>(new Object(),new ReferenceQueue<>());//虚引用
    private int paramInt = 1000;//八大基本类型
    private Object object = new Object();
    private boolean isOk = 10 / 2 == 4 ? true : false;
    public static void main(String[] args) {
        //循环,让堆内存发生YGC
        while (true) {
            Demo002JvmShow show = new Demo002JvmShow();
            User user = new User("拉丁");
            show.paramInt = user.getAge();
        }
    }
}

      JVM 采用的是【可达性分析算法】来判断一个对象是否可以被回收。这个算法的核心就是,通过判断对象是否还有被引用(这里又分强引用、软引用弱引用、虚引用而不同),也就是判断对象是否有GC Roots来进行回收。

      如果你的对象被局部变量、或者类的静态变量引用,GC就不会回收。比如当前执行到方法的show.paramInt = user.getAge(); 里面对象user,由于有main线程的虚拟机栈的user变量引用,这时候YGC是不会回收堆内存里的User对象。



然后对象里有很多变量,来看看哪些会被回收?


强引用的比如name,不能回收。

软引用的userB 对象可能会被回收,因为软引用,如果GC后空间够用就软引用的对象不会被回收,但是GC后空间还不够,那不好意思,软引用的对象也要被回收。

弱引用的userC,被回收。弱引用的对象,一旦发生GC,就会被回收。

如果一个对象没有GC Roots,是否也会被立马回收?

这个不一定。比如对象重写了finalize方法,并赋予新值。GC回收该对象之前,会调用它的finalize方法,如果它还有其他引用尤其是引用了自己,那就不能回收。

四、年轻代GC存活的对象什么时候进入老年代?

     年轻代的对象或者说新对象进入老年代主要有以下3个机制来控制。

    1、动态对象年龄判断机制。

           默认经过15次YGC ,也就是对象的年龄大于15之后,就被挪到老年代。

     2、空间担保机制。

           如果YGC后发现存活的对象比较多,且无法让新对象放到年轻代,然后老年代那边又有足够空间,能保证存下存活的全部对象,就把这些存活对象晋升到老年代存放。

     3、大对象

          如果新增的对象特别大,那这个大对象直接进入老年代。


今天分享到这,具体GC算法我们在下一篇文章分析。

相关文章
|
7月前
|
Arthas 存储 算法
深入理解JVM,包含字节码文件,内存结构,垃圾回收,类的声明周期,类加载器
JVM全称是Java Virtual Machine-Java虚拟机JVM作用:本质上是一个运行在计算机上的程序,职责是运行Java字节码文件,编译为机器码交由计算机运行类的生命周期概述:类的生命周期描述了一个类加载,使用,卸载的整个过类的生命周期阶段:类的声明周期主要分为五个阶段:加载->连接->初始化->使用->卸载,其中连接中分为三个小阶段验证->准备->解析类加载器的定义:JVM提供类加载器给Java程序去获取类和接口字节码数据类加载器的作用:类加载器接受字节码文件。
724 55
|
8月前
|
Arthas 监控 Java
Arthas memory(查看 JVM 内存信息)
Arthas memory(查看 JVM 内存信息)
706 6
|
7月前
|
Arthas 监控 Java
Arthas vmtool(从 jvm 里查询对象,执行 forceGc)
Arthas vmtool(从 jvm 里查询对象,执行 forceGc)
471 16
|
9月前
|
存储 缓存 算法
JVM简介—1.Java内存区域
本文详细介绍了Java虚拟机运行时数据区的各个方面,包括其定义、类型(如程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区和直接内存)及其作用。文中还探讨了各版本内存区域的变化、直接内存的使用、从线程角度分析Java内存区域、堆与栈的区别、对象创建步骤、对象内存布局及访问定位,并通过实例说明了常见内存溢出问题的原因和表现形式。这些内容帮助开发者深入理解Java内存管理机制,优化应用程序性能并解决潜在的内存问题。
427 29
JVM简介—1.Java内存区域
|
9月前
|
缓存 监控 算法
JVM简介—2.垃圾回收器和内存分配策略
本文介绍了Java垃圾回收机制的多个方面,包括垃圾回收概述、对象存活判断、引用类型介绍、垃圾收集算法、垃圾收集器设计、具体垃圾回收器详情、Stop The World现象、内存分配与回收策略、新生代配置演示、内存泄漏和溢出问题以及JDK提供的相关工具。
JVM简介—2.垃圾回收器和内存分配策略
|
10月前
|
存储 算法 Java
JVM: 内存、类与垃圾
分代收集算法将内存分为新生代和老年代,分别使用不同的垃圾回收算法。新生代对象使用复制算法,老年代对象使用标记-清除或标记-整理算法。
158 6
|
监控 Java 编译器
Java虚拟机调优指南####
本文深入探讨了Java虚拟机(JVM)调优的精髓,从内存管理、垃圾回收到性能监控等多个维度出发,为开发者提供了一系列实用的调优策略。通过优化配置与参数调整,旨在帮助读者提升Java应用的运行效率和稳定性,确保其在高并发、大数据量场景下依然能够保持高效运作。 ####
313 58
|
监控 架构师 Java
Java虚拟机调优的艺术:从入门到精通####
本文作为一篇深入浅出的技术指南,旨在为Java开发者揭示JVM调优的神秘面纱,通过剖析其背后的原理、分享实战经验与最佳实践,引领读者踏上从调优新手到高手的进阶之路。不同于传统的摘要概述,本文将以一场虚拟的对话形式,模拟一位经验丰富的架构师向初学者传授JVM调优的心法,激发学习兴趣,同时概括性地介绍文章将探讨的核心议题——性能监控、垃圾回收优化、内存管理及常见问题解决策略。 ####
|
存储 监控 算法
深入探索Java虚拟机(JVM)的内存管理机制
本文旨在为读者提供对Java虚拟机(JVM)内存管理机制的深入理解。通过详细解析JVM的内存结构、垃圾回收算法以及性能优化策略,本文不仅揭示了Java程序高效运行背后的原理,还为开发者提供了优化应用程序性能的实用技巧。不同于常规摘要仅概述文章大意,本文摘要将简要介绍JVM内存管理的关键点,为读者提供一个清晰的学习路线图。
JVM内存参数
-Xmx[]:堆空间最大内存 -Xms[]:堆空间最小内存,一般设置成跟堆空间最大内存一样的 -Xmn[]:新生代的最大内存 -xx[use 垃圾回收器名称]:指定垃圾回收器 -xss:设置单个线程栈大小 一般设堆空间为最大可用物理地址的百分之80