JVM专题六:JVM的内存模型中,我们介绍了JVM内存主要分哪些区域,这些区域分别是干什么的,同时也举了个例子,在运行过程种各个区域数据是怎样流转的。细心的小伙伴可能发现一个问题,在介绍完方法弹栈以后就没有介绍后续流程了。方法执行完以后,堆内存存放的对象实例咋整呢,带着这样的疑问进入今天的内容。
JVM垃圾回收机制是什么
1、为什么需要垃圾回收机制
同样带着这段代码进入今天的内容。
public class App {public static void main(String[] args) {runApp(args);System.out.println("====");}private static void runApp(String[] args) {SpringApplication sApp = new SpringApplication();sApp.run(App.class, args);
// sApp.getRunListeners(args);}
}public class SpringApplication {public String run(Class appClass, String[] args) {System.out.println("my Spring Application ");return "run args";}public String getRunListeners( String[] args) {System.out.println("My getRunListeners ");String myRunListenersVar = "myRunListenersVar";this.getSpringFactoriesInstances(args);return "run args";}public String getSpringFactoriesInstances( String[] args) {System.out.println("My getSpringFactoriesInstances ");String mySpringFactoriesInstancesVar = "mySpringFactoriesInstances";return "run args";}}
上述代码执行到了new的时候,我们会在JVM的堆内存中创建SpringApplication对象实例,并返回实例的引用给给局部变量持有。如下图所示:
再看下面JVM空间分布图会更加清晰:
代码继续执行,当run方法执行结束,run方法出栈以后引用不存在,此时JVM内存分配如下图所示:
核心点来了,此时大家应该都发现了,Java堆内存里的这个'Spring Application”实例对象已经没有人引用他了(特意换成白色不知道有没有小伙伴发现这个细节),这个对象实际上已经没用了,该干的事儿都干完了,JVM还让他留在内存里干啥呢?
在讨论JVM的时候我们时刻记住一个点内存资源是有限的。一般来说,我们会在一台机器上启动一个Java系统,机器的内存资源是十分有限的,比如常用的生产机器4核8G的内存,我们启动的Java系统本质就是一个JVM进程,他负责运行我们的系统的代码。那么这个JVM进程本身也是会占用机器上的部分内存资源,比如占用6G的内存资源,
那么我们在JVM的Java堆内存中创建的对象,其实本质也是会占用JVM的内存资源的,比如“SpringApplication”实例对象,假设会占用2kb的内存(实际更具对象的各个属性和运行时的资源实际会有不同大小)。
既然内存资源很紧张,且这个对象实例我们有没有作用,对于我们系统来说上述的2kb内存就是垃圾,对于垃圾我们自然需要进行处理。所以需要JVM垃圾回收机制。
2、JVM垃圾回收基本原理
Java虚拟机(JVM)的垃圾回收机制的基本工作原理,可以总结如下:
-
自动性:JVM启动时,会自动启动垃圾回收线程,这些线程在后台运行,不需要开发者手动触发。
-
持续监控:垃圾回收线程会持续监控JVM堆内存中的对象,检查它们是否还有活跃的引用。
-
引用检查:如果一个对象没有任何局部变量、静态变量、常量或其他方式的引用指向它,那么这个对象被认为是不可达的。
-
垃圾回收:对于不可达的对象,垃圾回收线程会将其标记为垃圾,并在适当的时候进行回收,释放它们占用的内存资源。
-
定期清理:垃圾回收是一个周期性的过程,它会定期执行,以清理不再需要的对象,从而维持内存的可用性。
-
资源释放:通过垃圾回收,JVM可以有效地管理内存资源,防止内存泄漏,并确保应用程序的持续运行。
-
性能考虑:虽然垃圾回收有助于内存管理,但其执行过程可能会暂时影响应用程序的性能,尤其是在进行Full GC时。
简而言之,JVM的垃圾回收机制是一个自动化的后台进程,它通过周期性地检查和回收不可达的对象(垃圾),帮助管理内存资源,确保应用程序的高效运行。
此时JVM内存如下图所示:
到目前为止,我们其实我们已经介绍了整个Java从源文件编译称class字节码,从字节码加载到JVM,JVM通过字节码执行器执行代码,执行过程中内存分布,执行结束后的垃圾处理。所以基本流程图应该可以回执出来啦。这时候回头看看专题一的整体图是不是更加清晰了呢: