1.JVM架构
解释:
- JVM有三个主要的子系统组成:(1)类加载器子系统 (2)运行时数据区,即java虚拟内存结构 (3)执行引擎。
- GC: Gabage Collection垃圾回收。
2.运行时数据区(重点分析)即jvm内存结构
运行时数据区,分为了五种类型区域,分别是:
- 方法区:它属于线程能共享,,类的方法及常量池。
- 堆:它属于线程能共享,,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堆是内存空间占据最大的一块数据区域)
根据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:
2.2 方法区
JDK1.7的时候,方法区称作为永久代,从JDK1.8开始,Metaspace(元空间)就是我们的方法区,元空间避免了永久代以前常出现内存溢出的问题,一个64位的服务器,默认的元空间-XX:MetaspaceSize值为21M。 方法区:和JAVA堆一样,也是各个线程共享的,存储虚拟机加载的类、常量、静态变量、即时编译器编译后的代码等数据。 只要类加载器还存活,其加载的类的元数据也是存活的,不会被回收掉,也是同生共死。
2.3 栈(线程栈)
每一个方法在执行的同时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息,每一个方法从调用直到执行完成的过程,就对应着一个栈帧在Java虚拟机栈中的入栈的出栈的过程。 局部变量表存放了编译其可知的各种基本数据类型、对象引用和returnAddress类型。
2.3 本地方法栈(线程栈)
和虚拟栈相似,只是服务于Native方法。
2.4 程序计数器
当前线程执行字节码的行号指标器,用于记录正执行的虚拟机字节指令地址,线程私有。