美文网首页
JVM 虚拟机及垃圾回收简介

JVM 虚拟机及垃圾回收简介

作者: 编程人生 | 来源:发表于2023-11-26 21:55 被阅读0次

    JVM虚拟机的体系结构

    1.方法区,方法区主要存方以下信息:

        1). 这个类的全限定名

         2).这个类型的访问修饰符

          3).字段信息(字段名,类型,修饰符P)和方法信息(方法名,返回类型,参数数量和类型,修饰符)。

            4).除了常量以外的所有类的静态变量。

    2.堆区

        Java程序在运行时所创建的所有对象实例都i放在同一个堆中,所有线程共享这个堆。优化虚拟机性能的主要工作是优化堆内存使用效率。

    3.栈区

        当我们启动一个线程时,Java虚拟机会为我们配一个Java 栈。

        Java 栈区中存储了线程中方法调用得到状态,包括局部变量,参数,返回值等。栈由许多栈帧组成,一个栈帧包含一个Java方法调用的状态。当线程调用一个方法时,虚拟机压入(push)一个新的栈帧到该线程的Java栈中,当该方法返回时,这个栈帧就从Java栈中弹出(pop)。

        如果线程请求的栈帧深度大于允许的深度,那么虚拟机就抛出StackOverflowError

    4.程序计数器

        java程序运行时,程序计数器总是指向下一条被执行指令的地址。

    5.本地(方法)接口和本地方法栈

        本地方法也称本地接口(Java Native Interface ,JNI). Java 线程可以调用本地方法,我们可以在Java线程中通过本地方法接口调用本地C++定义好的方法。

    6.执行引擎

        执行引擎也称字节码执行引擎,用来执行字节码。

    7.类加载子系统

        类加载子系统(也称类加载器)主要分为启动类加载器(BootStrapClassLoader),扩展类加载器

    (Extension ClassLoader),应用程序类加载器(Application ClassLoader)和用户自定义的类加载器(User Defined ClassLoader).

        和类加载器相关的两个异常:如果找不到类文件,会报 ClassNotFoundExecption异常;

        如果加载到的类中引用到的其他类不存在,则会报NoClassDelFoundError异常。

    分代管理和 Java垃圾收集机制

        堆内存结构:

    堆内存分代管理

    持久代(也称持久区)中主要存放的是Java类信息,或者在代码中通过import导入的类信息.

    在年轻代中一般会划分伊甸区和两个Survivor区

    垃圾回收的一般流程

        (1) new 出来的对象我们一般先到伊甸区Eden中申请空间,如果申请不到怎么办? 会把伊甸区中存活的对象复制到其中一个Survivor区中. 这里隐含了一个回收流程,当我们把伊甸区的对象复制到Survivor区时,把无用的对象回收了.

        (2)当伊甸区和其中一个Survivor区满了,会把伊甸区和其中一个Survivor区存活的对象再复制到另外一个Survivor区中,同样隐含了一次回收流程.

        (3) 如果年轻代的空间都满了,虚拟机会把年轻代中还存活的对象复制到年老代中

        (4) 当年老代满时(不会再复制到持久代了),会启动Full GC ,对年轻代\年老代\持久代进行全面回收.这耗费较长时间

    在上述的回收流程中,其实包含两类回收机制.

        1).轻量回收(Minor GC). 在年轻代中的回收都属于这种.这种回收中,一般都会用到一种效率相对较高的标记复制算法(Mar Copy),这种算法不涉及对无用对象的删除,只是把标记存活的对象从一个内存区复制到另一个内存区.

        2).重量级的Full GC流程,以下四种情况会触发这种GC

            2.1) 年老代(Tenured)被写满

            2.2)持久代被写满

            2.3)程序员显示的调用了Systerm.gc()方法.

            2.4)可以通过java命令分配堆空间的运行策略,如可以设置年轻代和年老代的比例,如果虚拟机监控到上次GC后,这种运行策略发生变化,也会触发Full GC.

    不重视内存性能可能会导致严重后果

            年轻代和年老代都写满了会触发FullGC,在执行FullGC时,会导致"Stop the World"情况的发生,也就是说虚拟机终止了所有Java程序,专门执行Full GC ,这就是卡住的原因.

    判断对象是否可以回收的依据

        标准很简单: 当某个对象存在强引用的情况时,不能回收.否则可以回收. 在绝大多数场景中,当某个对象上的最后一个强引用被撤去后,该对象不会被立即回收,而是在下次启动垃圾回收机制时候被回收.

        早期Java版本,采用"引用计数法 "来判断对象是否被引用. 很简单,对象被引用一次,加1.未被引用则为0.

    但有个缺点,无法解决"循环引用的情况". a引用b , b引用 c, c引用a 

        后续JDK版本,引入"根搜索算法".从根节点GC ROOT 开始寻找 引用的节点,直到找到最后一个节点. 未被找到节点也就是未被引用的节点,可以被回收.

        可以作为GC Root 对象有以下四个:

            1.虚拟机中引用的对象. 

            2.方法区中静态属性引用的对象.

            3.方法区中常量引用的对象

            4.本地方法栈中引用的对象.

    深入了解finalize方法:

        finalize() 是Object 类中的protected 类型的方法,子类可以通过覆盖整个方法来实现回收前的资源清理工作,与这个方法相关的流程如下:

        1) Java 虚拟机一旦通过"根搜索算法",判断出某对象处于可以回收的状态时,会判断该对象是否重写了

    Object 类的finalize 方法,如果没有,则直接回收.

        2).如果重写了finalize方法,而且未执行方法,则把该对象放到F-Queue 队列,另一个线程会定时遍历F-Queue队列,并执行队列中各对象的finalize方法.

        3).finalize方法执行完毕后,GC会再次判断该对象是否可被回收,如果可以,则进行回收;如果此时该对象上有强引用,则该对象"复活",即处于"不可回收状态".

    相关文章

      网友评论

          本文标题:JVM 虚拟机及垃圾回收简介

          本文链接:https://www.haomeiwen.com/subject/cfoawdtx.html