JVM 内存模型笔记

最近在看 《深入理解Java虚拟机》,准备边看书、边结合一些收集的资料以及自己在工作中的实践写一系列学习和总结的笔记,本篇文章为该系列的第一篇文章。

内存模型

书中和网络上都会通过(图1)描述JAVA的内存模型,内存中保存的数据即为运行时数据区,运行时数据区包含两类数据:

1.共享数据

      a. 方法区:静态变量、常量、加载的类信息等,永久代(PermGen)所属的区域;

      b. 堆区:实例对象和数组分配数据的区域,内存优化,GC回收优化基本上就是在对该区域做优化

    2.线程独有数据

      a.虚机栈:线程的变量、引用等数据;

      b.本地方法栈:调用非JAVA代码时候的内存数据,在有的JVM中,本地方法栈和虚机栈的处理是一致的

      c.程序计数器:保存当前线程执行指令的位置,计算机原理中常规的计数器的概念一致。


JVM 内存模型笔记_第1张图片
图 1  浅析Java虚拟机结构与机制

JVM这种内存模型设计的个人理解:JVM这样设计内存模型也是根据我们程序中的数据类型来区分的,和其他编程语言使用的内存模型基本上一致。堆区、栈区和全局数据区,堆区用来在内存上动态分配数据,栈区是每个线程所独有的数据,这里JVM根据数据类型又把栈区分为了三类,我觉得这是和JAVA这种依赖虚机语言特点的一种设计,内置数据类型必然和本地方法需要的数据类型在内存中存放的方式不一致有关系。

GC回收机制

这里主要简单记录一下堆空间的GC回收,在JVM中内存回收并不是一次性就完成的,而是将堆空间分为新生代和老年代,通过两次GC回收完成数据的回收,这种设计个人理解是和内存回收算法(关于GC回收的算法可以通Java垃圾回收机制简单了解)以及防止内存碎片产生有关的。

在堆空间中分为新生代和老年代,而新生代又分为eden、s0和s1(同一时刻,s0和s1只有其中一个区域存放着数据)。

新生代GC(Minor GC):当eden中内存不够用的时候就会触发一次GC回收(可以简单这么理解,因为在JVM设计中GC回收的触发是一个很复杂的策略,具体触发是有system决定的,老年代GC类似),这个时候采用的是复制算法,假如当前s0存放着数据,则会将eden和s0中还在使用的数据拷贝到s1中,并清空eden和s0,采用复制算法的优点就是快速,所以新生代会频繁进行GC。在上面那个过程中的,拷贝的数据年龄会被加1,当年龄达到一定程度的时候,数据会被回收的老年代。

老年代GC(Major GC  / Full GC):当老年代的内存不够的时候,触发一次老年代的内存回收,这个时候就不能用复制算法了,这样就需要消耗等量的内存来实现复制算法,此时使用的是标记压缩算法,而标记压缩算法是一个缓慢的过程。

所以不是直接将内存划分成一块区域,同时进行GC操作,而是根据内存回收频率分成两块,频繁回收和不频繁回收的,频繁回收的用空间换时间。


JVM 内存模型笔记_第2张图片
图2 堆空间内存回收示意图。

你可能感兴趣的:(JVM 内存模型笔记)