18、方法区与垃圾回收机制

目录

一.方法区

1.1.从哪里读class文件?

1.2.类型信息有哪些?

1.3.方法区中存储的类型信息与堆栈有何关系?

1.3.1.类加载阶段:

1.3.2.对象创建阶段:

1.3.3.方法调用阶段:

1.3.4.方法执行阶段:

1.3.5.方法返回阶段:

1.3.6.垃圾回收阶段:

二.垃圾回收机制

2.1.finalize方法

2.2.内存中的状态

2.3.强制垃圾回收


一.方法区

        当虚拟机(JVM)装载某个类型时(第一次读到,比如: new Car() ),它使用类装载器定位相应的class文件,然后读入class文件,并将它传输到虚拟机中。紧接着虚拟机提取其中的类型信息,并将这些信息存储到方法区。

1.1.从哪里读class文件?

        从硬盘、jar包、网络。

1.2.类型信息有哪些?

        class文件只会被加载一次,JVM从class文件中提取关键的内容。将类型信息解析提取后存入方法区,在程序其他地方用到该类的信息时(new Car()) 会从方法区去找。提取类型信息主要有两部分。第一部分是和类型直接相关的内容,第二部分是类中包含的内容。

类型直接相关的内容:

  • 这个类型的全限定名;
  • 这个类型的直接父类的全限定名;
  • 这个类型是类类型还是接口类型;
  • 这个类型的访问修饰符;
  • 直接接口的全限定名的有序列表(接口是多实现);

类中包含的内容:

  • 这个类型的常量池;
  • 这个类型的字段信息;
  • 这个类型的方法信息;
  • 除了常量以外的所有静态变量;
  • ……(类装载器,底层组件相关内容)

1.3.方法区中存储的类型信息与堆栈有何关系?

通过图片和示例代码来说明方法区与堆栈的关系。

18、方法区与垃圾回收机制_第1张图片

public class MyClass {
    private int number;
    private String name;

    public MyClass(int number, String name) {
        this.number = number;
        this.name = name;
    }

    public void someMethod() {
        System.out.println("Number: " + number + ", Name: " + name);
    }

    public static void main(String[] args) {
        MyClass obj = new MyClass(42, "Example"); // 触发类加载和对象创建
        obj.someMethod();
    }
}

1.3.1.类加载阶段

  • 当程序执行到MyClass obj = new MyClass(42, "Example");时,如果MyClass尚未被加载,JVM会触发类加载过程。

  • JVM通过类加载器查找并加载MyClass.class文件。

  • 加载后,JVM将MyClass类的类型信息(如类的结构信息、常量池、字段和方法数据等)放入方法区

1.3.2.对象创建阶段

  • JVM在当前线程的栈中为MyClass的构造方法创建一个新的栈帧,并将其压入栈顶。

  • 构造方法的栈帧中包含了构造方法的局部变量表、操作数栈、方法调用信息等。

  • 构造方法执行时,JVM在上为MyClass的对象分配内存,并根据方法区中存储的类的元数据(字段信息)初始化对象,完成初始化对象后构造方法出栈。

  • 对象的引用(即指向堆中对象的指针)被存储在main方法的栈帧的局部变量表中。

1.3.3.方法调用阶段

  • main方法调用obj.someMethod()时,JVM在当前线程的虚拟机栈中为someMethod创建一个新的栈帧,并将其压入栈顶。

  • someMethod的栈帧中包含了someMethod的局部变量表、操作数栈、方法调用信息等。

1.3.4.方法执行阶段

  • someMethod执行时,JVM从方法区中获取someMethod的字节码,并在当前栈帧的操作数栈中执行这些字节码。

  • someMethod中,访问对象的字段(如numbername)会使用堆中对象的内存地址。

1.3.5.方法返回阶段

  • someMethod执行完毕后,它的栈帧从虚拟机栈中弹出,控制权返回到main方法的栈帧。

  • main方法继续执行,直到结束,此时main方法的栈帧也从虚拟机栈中弹出。

1.3.6.垃圾回收阶段

  • main方法执行结束,JVM结束该线程,此时该线程的虚拟机栈会被销毁。

  • 垃圾回收器会定期检查堆中的对象,回收那些不再被任何栈帧引用的对象,以释放内存空间。

二.垃圾回收机制

        当程序创建引用类型数据时,JVM会在堆内存中为之分配一块内存区。当这份数据不再被任何变量引用时,它就成了垃圾,对应的内存区就等待垃圾回收器的回收。所以垃圾回收主要是针对堆而言的。垃圾回收有以下机制:

  • 垃圾回收器负责回收堆内存中的空间。

  • 程序无法精确的控制垃圾回收的时机。

  • 当数据永久的失去引用后,垃圾回收器会在合适的时候回收它的内存区。

2.1.finalize方法

        定义在 java.lang.Object 类中,所有的类都直接或间接继承Object类,finalize方法用于清理对象占用的资源。

protected void finalize() throws Throwable { }

  • 垃圾回收器在回收某对象的内存之前,会先调用它的finalize方法;

  • 针对某一个对象,垃圾回收器最多只会调用它的finalize方法一次。

  • 不要主动调用finalize方法,finalize方法何时调用,是否调用是不确定的!

2.2.内存中的状态

18、方法区与垃圾回收机制_第2张图片

  • 可达状态:若对象至少被一个变量引用,则该对象处于可达状态;

  • 可恢复状态:若对象不再被任何变量引用,它就进入了可恢复状态。此时垃圾回收器准备回收它的内存,并在回收前调用它的finalize方法;

  • 不可达状态:若在调用finalize方法后,对象依然未被引用,它就进入了不可达状态。只有对象进入了不可达状态,垃圾回收器才会回收该对象占据的内存空间!

2.3.强制垃圾回收

System.gc(); //静态方法

Runtime.getRuntime().gc(); //示例方法

        可以在程序中调用上述任意方法通知垃圾回收器进行垃圾回收,但是是否回收以及回收时机依然由垃圾回收器决定。这个代码相当于建议它垃圾回收,但决定权依旧在垃圾回收器手中。在实际中,很少会用到。

你可能感兴趣的:(JAVA基础知识,java,开发语言)