JVM运行时数据区总结(理论到实践)

运行时数据区总结

  • 背景
  • 程序计数器(线程私有)
    • 概念
    • 异常情况
    • 实战
  • 虚拟机栈(线程私有)
    • 概念
    • 异常情况
    • 实战
  • 堆内存(线程共享)
    • 概念
    • 异常情况
    • 实战
    • 参数
  • 方法区(线程共享)
  • 运行时常量池(方法区的一部分)
  • 本地方法栈(线程私有)

JVM运行时数据区总结(理论到实践)_第1张图片

背景

读了很久的Java虚拟机这本书,现在准备将平时整理的笔记总结一下,其中还包括看视频、看文章的一些补充内容,上面这张图是java执行的整个流程,以后的文章将会围绕这张图展开,具体的描述class文件的组成、类加载子系统的原理、对象的分配、执行引擎的原理和GC垃圾回收等等,这篇文章主要总结一下运行时数据区,可以参考Oracle官网Jvm规范

程序计数器(线程私有)

概念

程序计数器记录字节码执行的位置,在多线程中,起到切换线程的时候提示当前线程执行的位置

异常情况

程序计数器是唯一一个没有内存溢出的模块

实战

下面这张图是class文件反汇编出来的文件,上面的红圈就是程序计数器记录的执行到那条指令的位置
JVM运行时数据区总结(理论到实践)_第2张图片

虚拟机栈(线程私有)

概念

虚拟机栈使用栈帧(用来存储局部变量表、操作数帧、动态连接、方法出口)标记方法的出栈入栈,使用递归可以会使用很多的栈帧,当线程请求的栈深入大于虚拟机所允许的深度,会导致栈深度溢出(StackOverFlowError)问题
虚拟机栈里包含了一个局部变量表,里面存储8种数据类型、对象的句柄和returnAddress类型(指向了一条字节码指令的地址),当栈扩展时内存不够时,会出现内存溢出(OOM)

异常情况

StackOverFlowError、OOM

实战

模拟栈异常:最简单的是执行一个递归
JVM运行时数据区总结(理论到实践)_第3张图片

堆内存(线程共享)

概念

堆内存主要保存的是new出来的对象,当内存不够的时候会出现内存溢出(OOM)
堆内存被分为新生代、老年代,新生代又分为Eden、Survivor(默认8:1:1)

异常情况

OOM

实战

设置jvm参数-Xms20M -Xmx20M,-Xms:初始堆大小 ,-Xmx:最大堆大小 ,这里我们设置最大堆大小为20M,我们new的数组大小为100M,所以出现内存溢出
JVM运行时数据区总结(理论到实践)_第4张图片

参数

-Xms:初始堆大小
-Xmx:最大堆大小
-XX:NewSize=n:设置年轻代大小
-XX:NewRatio=n:设置年轻代和年老代的比值.如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4
-XX:SurvivorRatio=n:年轻代中Eden区与两个Survivor区的比值.注意Survivor区有两个.如:3,表示Eden:Survivor=3:2,一个Survivor区占整个年轻代的1/5
-XX:MetaspaceSize=n:设置元空间大小

方法区(线程共享)

方法区用于存放已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据,如果方法区无法满足新的内存分配需求时,会报OOM

运行时常量池(方法区的一部分)

常量池表用于存放编译器生成的各种字面量与符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中,当常量池无法申请到内存时会抛出OOM

本地方法栈(线程私有)

本地方法栈与虚拟机栈的区别是只服务与native关键字的方法

你可能感兴趣的:(JVM系列,jvm,java)