JVM内存模型、堆内存分配以及垃圾回收机制(GC)

    科技2022-07-11  81

    1.什么是JVM

    JRE(JavaRuntimeEnvironment,Java运行环境),也就是Java平台。所有的Java 程序都要在JRE下才能运行。普通用户只需要运行已开发好的java程序,安装JRE即可。 JVM(JavaVirtualMachine,Java虚拟机)是JRE的一部分。它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。JVM有自己完善的硬件架构,如处理器、堆栈、寄存器等,还具有相应的指令系统。Java语言最重要的特点就是跨平台运行。使用JVM就是为了支持与操作系统无关,实现跨平台。 JDK(Java Development Kit)是程序开发者用来来编译、调试java程序用的开发工具包。JDK的工具也是Java程序,也需要JRE才能运行。为了保持JDK的独立性和完整性,在JDK的安装过程中,JRE也是 安装的一部分。所以,在JDK的安装目录下有一个名为jre的目录,用于存放JRE文件。

    2.JVM内存模型

    图片来源:牛客网用户 【菜鸟葫芦娃】 ========================================================================= 大多数 JVM 将内存区域划分为 Method Area(Non-Heap)(方法区) ,Heap(堆) , Program Counter Register(程序计数器) , VM Stack(虚拟机栈,也有翻译成JAVA方法栈的),Native Method Stack ( 本地方法栈 ),其中Method Area 和 Heap 是线程共享的 ,VM Stack,Native Method Stack 和Program Counter Register 是非线程共享的。

    概括地说来,JVM初始运行的时候都会分配好 Method Area(方法区) 和Heap(堆) ,而JVM 每遇到一个线程,就为其分配一个 Program Counter Register(程序计数器) , VM Stack(虚拟机栈)和Native Method Stack (本地方法栈), 当线程终止时,三者(虚拟机栈,本地方法栈和程序计数器)所占用的内存空间也会被释放掉。这也是为什么把内存区域分为线程共享和非线程共享的原因,非线程共享的那三个区域的生命周期与所属线程相同,而线程共享的区域与JAVA程序运行的生命周期相同,所以这也是系统垃圾回收的场所只发生在线程共享的区域(实际上对大部分虚拟机来说知发生在Heap上)的原因。

    来自牛客网用户 【牛客235607号】

    3.堆内存的分配和垃圾回收机制

    java进程运行过程中创建的对象存放在堆中,堆被划分成两个不同的区域:新生代 ( Young )、老年代 ( Old )。新生代 ( Young ) 又被划分为三个区域:Eden、From Survivor、To Survivor。

    堆大小设置 java -Xmx3550m -Xms3550m -Xss128k -XX:NewRatio=4 -XX:SurvivorRatio=4

    Xmx3550m :设置JVM最大可用内存为3550M。Xms3550m :设置JVM初始内存为3550m。Xmn2g :设置年轻代大小为2G。整个堆大小=年轻代大小 + 年老代大小 + 持久代大小。Xss128k :设置每个线程的堆栈大小。XX:NewRatio=4 :设置年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代)。设置为4,则年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5。XX:SurvivorRatio=4 :设置年轻代中Eden区与Survivor区的大小比值。设置为4,则两个Survivor区与一个Eden区的比值为2:4,一个Survivor区占整个年轻代的1/6。

    垃圾回收机制

    老生代的Mark-Compact算法

    上图为标记-整理前,进行标记整理时,jvm会将灰色的都往前移,让黑色的都在灰色后面,效果如下。

    然后以最后一个灰色的为边界,将边界外的内存空间清除掉。形成的效果如下。

    ========================================================================

    新生代的Copying算法

    此时进行对新生代的垃圾回收,要将Eden中所有灰色的对象复制到Survivor1中,其年龄+1,然后对Eden空间和Survivor2空间进行清除。效果如下图:

    然后继续使用,新创建的对象放在Eden空间中,当放不下了需要垃圾回收时,进行标记,此时Survivor1中的对象也要标记。如下图所示。

    此时,将Eden空间和Survivor1中存活对象复制到Survivor2中,其对象年龄+1,并将Eden空间和Survivor1空间清除。结果如下图: 针对新生代的垃圾回收,我们叫minor gc,针对老年代的垃圾回收,我们叫major gc,而针对新生代和老年代的全局垃圾回收,我们叫full gc。这里针对老年代的gc很少,只有cms收集器用,并且cms也基本用的很少了,所以这里就不讨论major gc了,只考虑minor gc 和full gc。 当新生代空间不足时,会触发minor gc,此时如果回收不理想,对象在Eden中放不下,则会考虑放在老年代的内存空间中,如果老年代也放不下,此时会触发full gc,在full gc之前,还会先尝试一次minor gc。 当Survivor空间放不下Eden中存活的对象时,会直接将其放入老年代。 来源:https://blog.csdn.net/qq_34687559/article/details/105935764?depth_1-

    Processed: 0.024, SQL: 8