JVM工作原理与实战(二十二):方法区的垃圾回收

简介: JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了Java的内存管理和自动垃圾回收、方法区的垃圾回收等内容。

一、Java的内存管理和自动垃圾回收

运行时数据区知识回顾

Java虚拟机(JVM)在运行Java程序期间,会创建并维护一系列内存区域,这些区域总称为运行时数据区。这些区域根据其用途和特性,被严格定义并管理。《Java虚拟机规范》详细规定了这些区域的作用和行为,以确保所有Java虚拟机实现的一致性和正确性。

线程不共享区域:

  • 程序计数器:用于存储当前线程执行的字节码指令地址。这个区域是每个线程独有的,不共享。
  • Java虚拟机栈:每个线程在创建时都会创建一个虚拟机栈,每个方法调用都会创建一个栈帧,用于存储局部变量、操作数栈、动态链接和方法出口信息。
  • 本地方法栈:与虚拟机栈相似,本地方法栈为native方法提供服务。

线程共享区域:

  • 方法区:用于存储已被JVM加载的类信息、常量、静态变量以及即时编译器编译后的代码等数据。
  • 堆:堆是所有线程共享的区域,用于动态分配内存。所有的对象实例以及数组都应当在堆上分配。

image.gif

在运行时数据区中,线程不共享的部分都是伴随着线程的创建而创建,随着线程的销毁而销毁。而方法的栈帧在执行完方法之后就会自动弹出栈并释放掉对应的内存。这种内存管理方式可以有效地减少内存的浪费,并且可以防止内存泄漏问题的发生。

image.gif

二、方法区的垃圾回收

1.回收条件

在Java中,方法区用于存储已被虚拟机加载的类信息、常量、静态变量以及即时编译器编译后的代码等数据。与堆区一样,方法区也有垃圾回收机制,主要是对不再使用的类进行回收。

要判定一个类是否可以被卸载,需要同时满足以下三个条件:

  • 此类所有的实例对象都已经被回收,即在堆区中不存在该类的任何实例对象和子类对象。
  • 加载该类的类加载器已经被回收。在Java中,类加载器通过ClassLoader类实现,当一个类加载器不再被引用,或者其父类加载器也被回收时,该类加载器会被回收。
  • 该类对应的java.lang.Class对象没有被其他对象引用。如果一个Class对象没有被其他任何对象引用,那么这个Class对象可以被回收。

2.手动触发垃圾回收

虽然垃圾回收是自动进行的,但在某些情况下,可能需要手动触发垃圾回收。这可以通过调用System.gc()方法实现。这个方法会向Java虚拟机发送一个请求,要求进行垃圾回收。

System.gc();

image.gif

需要注意的是,调用System.gc()并不一定会立即执行垃圾回收。Java虚拟机可能会根据当前的运行情况自行判断是否需要进行垃圾回收。因此,手动触发垃圾回收并不一定能够提高程序的性能。

在开发中,手动触发垃圾回收的情况并不常见。但在一些特殊的应用场景中,如OSGi框架和JSP的热部署等,可能需要手动触发垃圾回收。在这些场景中,当一个jsp文件被修改后,对应的类加载器会被卸载,然后重新创建类加载器并重新加载jsp文件。

3.方法区的垃圾回收案例

案例:

此类所有的实例对象都已经被回收,即在堆区中不存在该类的任何实例对象和子类对象。

public class Demo1 {
    public static void main(String[] args) throws InterruptedException {
        try {
            URLClassLoader loader = new URLClassLoader(new URL[]{new URL("file:D:\\Test\\")});
            Class<?> clazz = loader.loadClass("com.rye.test.Test");
            Object o = clazz.newInstance();
            o = null;
            System.gc();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
image.gif

image.gif

案例:

加载该类的类加载器已经被回收。在Java中,类加载器通过ClassLoader类实现,当一个类加载器不再被引用,或者其父类加载器也被回收时,该类加载器会被回收。

public class Demo1 {
    public static void main(String[] args) throws InterruptedException {
        try {
            URLClassLoader loader = new URLClassLoader(new URL[]{new URL("file:D:\\Test\\")});
            Class<?> clazz = loader.loadClass("com.rye.test.Test");
            Object o = clazz.newInstance();
            loader = null;
            System.gc();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
image.gif

image.gif

案例:

该类对应的java.lang.Class对象没有被其他对象引用。如果一个Class对象没有被其他任何对象引用,那么这个Class对象可以被回收。

public class Demo1 {
    public static void main(String[] args) throws InterruptedException {
        try {
            URLClassLoader loader = new URLClassLoader(new URL[]{new URL("file:D:\\Test\\")});
            Class<?> clazz = loader.loadClass("com.rye.test.Test");
            Object o = clazz.newInstance();
            clazz = null;
            System.gc();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
image.gif

image.gif

总结

JVM是Java程序的运行环境,负责字节码解释、内存管理、安全保障、多线程支持、性能监控和跨平台运行。本文主要介绍了Java的内存管理和自动垃圾回收、方法区的垃圾回收等内容,希望对大家有所帮助。

相关文章
|
2月前
|
存储 监控 算法
美团面试:说说 G1垃圾回收 底层原理?说说你 JVM 调优的过程 ?
尼恩提示: G1垃圾回收 原理非常重要, 是面试的重点, 大家一定要好好掌握
美团面试:说说 G1垃圾回收 底层原理?说说你 JVM 调优的过程  ?
|
2月前
|
监控 架构师 Java
JVM进阶调优系列(6)一文详解JVM参数与大厂实战调优模板推荐
本文详述了JVM参数的分类及使用方法,包括标准参数、非标准参数和不稳定参数的定义及其应用场景。特别介绍了JVM调优中的关键参数,如堆内存、垃圾回收器和GC日志等配置,并提供了大厂生产环境中常用的调优模板,帮助开发者优化Java应用程序的性能。
|
2月前
|
存储 监控 算法
JVM调优深度剖析:内存模型、垃圾收集、工具与实战
【10月更文挑战第9天】在Java开发领域,Java虚拟机(JVM)的性能调优是构建高性能、高并发系统不可或缺的一部分。作为一名资深架构师,深入理解JVM的内存模型、垃圾收集机制、调优工具及其实现原理,对于提升系统的整体性能和稳定性至关重要。本文将深入探讨这些内容,并提供针对单机几十万并发系统的JVM调优策略和Java代码示例。
55 2
|
2月前
|
算法 Java 开发者
Java中的垃圾回收机制:从原理到实践
Java的垃圾回收机制(Garbage Collection, GC)是其语言设计中的一大亮点,它为开发者提供了自动内存管理的功能,大大减少了内存泄漏和指针错误等问题。本文将深入探讨Java GC的工作原理、不同垃圾收集器的种类及它们各自的优缺点,并结合实际案例展示如何调优Java应用的垃圾回收性能,旨在帮助读者更好地理解和有效利用Java的这一特性。
|
2月前
|
算法 JavaScript 前端开发
垃圾回收算法的原理
【10月更文挑战第13天】垃圾回收算法的原理
24 0
|
3月前
|
监控 算法 Java
深入理解Java中的垃圾回收机制在Java编程中,垃圾回收(Garbage Collection, GC)是一个核心概念,它自动管理内存,帮助开发者避免内存泄漏和溢出问题。本文将探讨Java中的垃圾回收机制,包括其基本原理、不同类型的垃圾收集器以及如何调优垃圾回收性能。通过深入浅出的方式,让读者对Java的垃圾回收有一个全面的认识。
本文详细介绍了Java中的垃圾回收机制,从基本原理到不同类型垃圾收集器的工作原理,再到实际调优策略。通过通俗易懂的语言和条理清晰的解释,帮助读者更好地理解和应用Java的垃圾回收技术,从而编写出更高效、稳定的Java应用程序。
|
2月前
|
前端开发 Java 应用服务中间件
JVM进阶调优系列(1)类加载器原理一文讲透
本文详细介绍了JVM类加载机制。首先解释了类加载器的概念及其工作原理,接着阐述了四种类型的类加载器:启动类加载器、扩展类加载器、应用类加载器及用户自定义类加载器。文中重点讲解了双亲委派机制,包括其优点和缺点,并探讨了打破这一机制的方法。最后,通过Tomcat的实际应用示例,展示了如何通过自定义类加载器打破双亲委派机制,实现应用间的隔离。
|
3月前
|
监控 算法 Java
掌握Java的垃圾回收机制:从原理到实践
在Java的世界中,垃圾回收(Garbage Collection,简称GC)是一块神秘的领域,它如同一位默默无闻的清洁工,确保内存中不再使用的对象得到妥善处理。本文将带你走进垃圾回收的大门,探索它的工作原理、常见算法及其在实际应用中的调优策略。无论你是初学者还是有一定经验的开发者,这篇文章都将为你揭开垃圾回收的神秘面纱,让你的Java程序运行得更加高效和稳定。
65 5
|
4月前
|
存储 安全 Java
JVM常见面试题(二):JVM是什么、由哪些部分组成、运行流程,JDK、JRE、JVM关系;程序计数器,堆,虚拟机栈,堆栈的区别是什么,方法区,直接内存
JVM常见面试题(二):JVM是什么、由哪些部分组成、运行流程是什么,JDK、JRE、JVM的联系与区别;什么是程序计数器,堆,虚拟机栈,栈内存溢出,堆栈的区别是什么,方法区,直接内存
JVM常见面试题(二):JVM是什么、由哪些部分组成、运行流程,JDK、JRE、JVM关系;程序计数器,堆,虚拟机栈,堆栈的区别是什么,方法区,直接内存
|
4月前
|
存储 缓存 Java
JVM中的方法区
这篇文章介绍了JVM中方法区的概念和作用,包括它所存储的内容(类型信息、常量、静态变量、编译后的代码缓存),常量池与运行时常量池的功能,以及方法区与栈、堆的交互关系。
JVM中的方法区