码迷,mamicode.com
首页 > 其他好文 > 详细

JVM 系列(二)内存模型

时间:2018-07-01 11:53:41      阅读:211      评论:0      收藏:0      [点我收藏+]

标签:ati   区域   new   font   一个栈   内存   深度   堆转储   flow   

02 JVM 系列(二)内存模型

技术分享图片

一、JVM 内存组成

(1) PC 寄存器(线程私有)

Java 虚拟机会为每个线程创建 PC 寄存器,在任意时刻,一个 java 线程总是在执行一个方法,这个方法被称为当前方法。

如果当前方法不是本地方法,PC 寄存器就会执行当前正在被执行的指令,如果是本地方法,则 PC 寄存器值为 undefined,寄存器存放如当前执行环境指针、程序计数器、操作栈指针、计算的变量指针等信息。

这个内存区域是唯一一个在虚拟机中没有规定任何 OutOfMemoryError 情况的区域。

(2) Java 虚拟机栈(线程私有)

每个方法在执行的时候会创建一个栈帧,存储了局部变量表,操作数栈,动态连接,方法返回地址等。每个方法从调用到执行完毕,对应一个栈帧在虚拟机栈中的入栈和出栈。通常所说的栈,一般是指虚拟机栈中的局部变量表部分。局部变量表所需的内存在编译期间完成分配。

如果线程请求的栈深度大于虚拟机所允许的深度,则 StackOverflowError。如果虚拟机栈可以动态扩展,扩展到无法申请足够的内存,则 OutOfMemoryError。

(3) 本地方法栈(线程私有)

本地方法栈和 Java 栈非常类似,最大不同为本地方法栈用于本地方法调用。Java 虚拟机允许 Java 直接调用本地方法(通常使用C编写)。

也会抛出 StackOverflowError 和 OutOfMemoryError。

(4) Java 堆(线程共享)

Java 虚拟机启动的时候建立 Java 堆,它是 Java 程序最主要的内存工作区域,几乎所有的对象实例都存放到 Java 堆中,堆空间是所有线
被所有线程共享的。堆可以按照可扩展来实现:-Xmx(最大内存) 和 -Xms(初始化内存)

当堆中没有内存可以分配给实例,也无法再扩展时,则抛出 OutOfMemoryError 异常。

(5) 方法区(线程共享)

用于存储已被虚拟机加载的类信息,常量,静态变量等。这个区域的内存回收目标主要针对常量池的回收和对类型的卸载。

当方法区无法满足内存分配需求时,则抛出 OutOfMemoryError 异常。

JDK1.7 中,已经把放在永久代的字符串常量池移到堆中。JDK1.8 撤销永久代,引入元空间。

(6) 运行时常量池

是方法区的一部分,用于存放编译期生成的各种字面量和符号引用。当常量池无法再申请到内存时,则抛出 OutOfMemoryError 异常。

(7) 直接内存

Java 的 NIO 库允许 Java 程序使用直接内而提高性能,通红接内存速度会优于 java 堆。读写频繁的场合可能会考虑使用。

直接内存不是运行时数据区的一部分,但也可能抛出 OutOfMemoryError 异常。

总结:

名称 特征 作用 配置 异常
栈区 线程私有,使用一段连续的内存空间 存放局部变量表、操作栈、动态链接、方法出口 -Xss StackOverflowError OutOfMemoryError
线程共享,生命周期与虚拟机相同 保存对象实例 -Xms -Xmx -Xmn OutOfMemoryError
程序计数器 线程私有、占用内存小 字节码行号
方法区 线程共享 存储类加载信息、常量、静态变量等 -XX:PermSize -XX:MaxPermSize OutOfMemoryError

二、java 堆和 GC

java 堆是和 java 应用程序关系最密切的内存空间,几乎所有的对象都存放在其中,并且 java 堆完全是自动化管理的,通过垃圾回收机制,垃圾对象会自动清理,不需要显示地释放。 Java 中的堆也是 GC 收集垃圾的主要区域。

技术分享图片

根据垃圾回收机制不同,其中堆有可能拥有不同的结构:

  1. java 堆分为新生代和老年代。新生代存放新生的对象或者年龄不大的对象,老年代则存放老年对象。
  2. 堆大小 = 新生代 + 老年代。其中,堆的大小可以通过参数 –Xms、-Xmx 来指定。新生代与老年代的比例通过参数 –XX:NewRatio 来指定。
  3. 新生代分为 eden 区、s0 区、s1 区,s0 和 s1 也被称为 from 和 to 区域,他们是两块大小相等并且可以互换角色的空间。Edem与from的比例通过参数 –XX:SurvivorRatio 来指定。
  4. Minor GC 采用的是复制算法,将还存活的对象从 s0 拷贝到 s1 区。
  5. 绝大多数情况下,对象首先分配在 eden 区,在一次新生代回收后,如果对象还存活,则会进入 s0 或者 s1 区,之后每经过一次新生代向收,如果对象存活则它的年龄就加 1。

三、参数配置

参数 说明
-Xms 初始堆大小。如:-Xms256m
-Xmx 最大堆大小。如:-Xmx512m
-Xmn 新生代大小。通常为 Xmx 的 1/3 或 1/4。新生代 = Eden + 2 个 Survivor 空间。实际可用空间为 = Eden + 1 个 Survivor,即 90%
-Xss JDK1.5+ 每个线程堆栈大小为 1M,一般来说如果栈不是很深的话, 1M 是绝对够用了的。
-XX:NewRatio 新生代与老年代的比例,如 –XX:NewRatio=2,则新生代占整个堆空间的1/3,老年代占2/3
-XX:SurvivorRatio 新生代中 Eden 与 Survivor 的比值。默认值为 8。即 Eden 占新生代空间的 8/10,另外两个 Survivor 各占 1/10
-XX:PermSize 永久代(方法区)的初始大小
-XX:MaxPermSize 永久代(方法区)的最大值
-XX:+PrintGCDetails 打印 GC 信息
-XX:+HeapDumpOnOutOfMemoryError 让虚拟机在发生内存溢出时 Dump 出当前的内存堆转储快照,以便分析用

每天用心记录一点点。内容也许不重要,但习惯很重要!

JVM 系列(二)内存模型

标签:ati   区域   new   font   一个栈   内存   深度   堆转储   flow   

原文地址:https://www.cnblogs.com/binarylei/p/9249563.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!