jvm——运行时数据区域

《深入理解Java虚拟机》是一本能让java开发者废寝忘食的书。
最初拿到这本书,自己还是一个完全懵懂、“知其然而不知其所以然”的java菜鸟,现在可能好一点了,这本书也来来回回翻了好几遍,对jvm有了一定的认识。最近要找工作,又重新学习了下,总结一下一些基本的知识点。
本文主要总结一下jvm的运行时数据区域

总览

平时开发时,我们并不用关心jvm底层的东西,像new对象,我们只管new,jvm的垃圾回收机制会自动帮我们管理好内存。但是,随着程序的体量增大,功能变得复杂,慢慢程序会时常报出内存泄露、内存溢出这类问题,这就需要传说中的jvm调优的技能了,掌握这项技能,首先就要了解jvm的运行时数据区域

jvm的运行时数据区域:

  1. 程序计数器
  2. java虚拟机栈
  3. 本地方法栈
  4. java堆
  5. 方法区
  6. 直接内存

程序计数器

程序计数器:Program Counter Register,是一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器。
是否线程私有:是
是否会报出异常:否

要点:

  1. 字节码解释器工作时,依赖该计数器来获取下一条需要执行的字节码指令,比如程序中的分支、循环、跳转、异常处理等,代码不是顺序执行,需要依赖该计数器来实现。
  2. 多线程情况下,每个线程轮流切换cpu的使用权。当某线程再次获得cpu使用权,需要使用该计数器来恢复正确的执行位置。
  3. 线程执行的java方法,计数器记录正在执行的虚拟机字节码指令地址;如果是Native本地方法,计数器值为空(Undefined)。

java虚拟机栈

java虚拟机栈:Java Virtual Machine Stacks,描述的是java方法执行的内存模型:每个方法在执行的同时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每个方法从调用到执行完成的过程,对应着一个栈帧在虚拟机栈中入栈到出栈的过程
是否线程私有:是,并且,它的生命周期和当前线程相同
是否会报出异常:是,1.如果线程请求的栈深度大于虚拟机所允许的深度,抛出StackOverflowError;2.如果虚拟机栈是动态扩展的,没有固定深度,一直申请开线程,内存耗尽,抛出OutOfMemoryError.

解释局部变量表
存放编译期可知的各种基本数据类型(byte,short,int,long,char,boolean,float,double)、对象引用(reference类型)和returnAddress类型。
局部变量表的大小,在编译期就确定了,方法运行期间不会改变的。

本地方法栈

本地方法栈:Native Method Stack,执行Native本地方法。
是否线程私有:是
是否会报出异常:是,平时所用的Sun HotSpot 虚拟机把本地方法栈和java虚拟机栈合为一起,所以异常是一样的。

java堆

java堆:java Heap,是java虚拟机所管理的内存中最大的一块,几乎所有对象实例都分配在堆中。
是否线程私有:否,所有线程共享
是否会报出异常:是,当给某对象分配内存,发现内存耗尽,抛出OutOfMemoryError。

要点:

  1. “几乎所有对象实例都分配在堆中”中,用到“几乎”,是因为虚拟机后续的一系列优化,也有对象直接放到栈上,比如,逃逸分析技术
  2. 堆是垃圾收集器管理的主要区域,称为GC堆。由于垃圾回收使用分代算法,堆又分为:新生代和老年代。其中新生代使用的复制算法,新生代又被分为8:1:1。
  3. 配置参数-Xmx(最大堆内存)和-Xms(最小堆内存)。

方法区

方法区:Method Area,存储已被虚拟机加载的类信息,常量,静态变量,即使编译器编译后的代码等数据
是否线程私有:否,各个线程共享的内存区域
是否会报出异常:是,内存耗尽,抛出OutOfMemoryError。

要点:

  1. 方法区也就是垃圾回收所说的永久代,限定在HotSpot虚拟机
  2. JDK1.7的HotSpot中,把原来属于永久代的字符串常量池移除
  3. 垃圾回收时,主要是针对常量池的回收和对类型的卸载,一般回收比较少
  4. 配置参数XX:PermSize和XX:MaxPermSize

运行时常量池:

  1. 方法区的一部分
  2. class文件中的常量池,在该class加载后,会存放到运行时常量池
  3. 动态性,除了class文件中的常量池内容放进去,运行期间可以将新的常量放入池中
  4. 常量池无法申请到内存,则抛出OutOfMemoryError

直接内存

直接内存:Direct Memory,并不是运行时数据区域的一部分,但是该区域被频繁使用。比如NIO
是否线程私有:否
是否会报出异常:是,受限制于机器的总内存,一旦申请不到内存,抛出OutOfMemoryError

文章目录
  1. 1. 总览
    1. 1.1. 程序计数器
    2. 1.2. java虚拟机栈
    3. 1.3. 本地方法栈
    4. 1.4. java堆
    5. 1.5. 方法区
    6. 1.6. 直接内存
|