JVM 内存结构

297 阅读3分钟

1.JVM架构

2019120710435597.png 解释:

  • JVM有三个主要的子系统组成:(1)类加载器子系统 (2)运行时数据区,即java虚拟内存结构 (3)执行引擎。
  • GC: Gabage Collection垃圾回收。

2.运行时数据区(重点分析)即jvm内存结构

image.png 运行时数据区,分为了五种类型区域,分别是:

  • 方法区:它属于线程能共享,,类的方法及常量池。
  • 堆:它属于线程能共享,,new对象存放地。
  • 栈(线程栈):它属于线程私有。
  • 本地方法栈:它属于线程私有, java Native访问本地C/C++的dll等。
  • 程序计数器:它属于线程私有,线程的代码行号记录。

GC(垃级回收)的分类

JVM进行GC时,主要针对三个区域进行垃圾回收:堆(新生代和老年代)、方法区,大部分回收是堆中的新生代,GC的四种类型:

  • Minor GC(又叫Young GC): 只针对新生代的垃圾回收,当Eden区满时触发GC,Survivor不会触发Minor GC。
  • Major GC(又叫Old GC): 只针对老年代区的垃圾收集,目前只有CMS收集器会有单独收集老年代的行为。
  • Mixed GC(混合收集): 指目标是收集整个新生代以及部分老年代的垃圾集,目前只有G1收集器会有这种行为。
  • Full GC(整堆收集): 收集整个Java堆和方法区的垃圾收集。

2.1 堆(别名GC堆,垃圾回收的主营地,JAVA堆是内存空间占据最大的一块数据区域)

image.png

根据JAVA对象存活时间的不同是,进行划分:

JAVA堆=新生代+老年代

新生代=Eden+ From Survivor 0 + To Survivor 1,

简写Eden+S0+S1,翻译:伊甸园区,幸运区0,幸运区1。

默认大小比例:Eden:from :to=8:1\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\:1

堆的JVM常见参数:(在JDK1.8开始有了元空间区(Matespace)来替换永久代(Permanent Generation),那么在设置JVM参数的时候,也要增加上Matespace的相关参数了。)

-Xms: 堆容量初始大小(堆包括新生代和老年代)。 例如:-Xms 512M -Xmx: 堆总共(最大)大小。 例如:-Xmx 512M -Xmn: 新生代容量大小。例如:-Xmn 10M -XX: SurvivorRatio 设置参数Eden、form和to的比例 【比例参数Eden、form和to默认是8:1:1】例如:-XX: SurvivorRatio=8 代表比例8:1:1

虽然没有直接设置老年代的参数,但是可以设置堆空间大小和新生代空间大小两个参数来间接控制: 老年代空间大小 = 堆空间大小 - 年轻代大空间大小

例子:据于jdk1.8的jvm参数调优,原则尽量调大年轻代内存的大小,避免老年代数据区的GC:

image.png

2.2 方法区

JDK1.7的时候,方法区称作为永久代,从JDK1.8开始,Metaspace(元空间)就是我们的方法区,元空间避免了永久代以前常出现内存溢出的问题,一个64位的服务器,默认的元空间-XX:MetaspaceSize值为21M。 方法区:和JAVA堆一样,也是各个线程共享的,存储虚拟机加载的类、常量、静态变量、即时编译器编译后的代码等数据。 只要类加载器还存活,其加载的类的元数据也是存活的,不会被回收掉,也是同生共死。

2.3 栈(线程栈)

每一个方法在执行的同时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息,每一个方法从调用直到执行完成的过程,就对应着一个栈帧在Java虚拟机栈中的入栈的出栈的过程。 局部变量表存放了编译其可知的各种基本数据类型、对象引用和returnAddress类型。

2.3 本地方法栈(线程栈)

和虚拟栈相似,只是服务于Native方法。

2.4 程序计数器

当前线程执行字节码的行号指标器,用于记录正执行的虚拟机字节指令地址,线程私有。