JVM 系列(二)内存模型

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 出当前的内存堆转储快照,以便分析用


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

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

时间: 2024-08-05 15:26:39

JVM 系列(二)内存模型的相关文章

Java 进阶(一) JVM运行时内存模型

1.JVM运行时数据区域的划分 a.程序计数器(Program Counter Register) 一块较小的内存空间,可以看作是当前线程所执行的字节码的行号指示器.每个线程拥有独立的一个计数器,如果当前执行的是Native方法,则计数器值为空. b.JVM栈(Java Virtual Machine Stack) 描述Java方法执行的内存模型,每个方法在执行的同时都会创建一个栈帧(Stacks Frame)用于存储局部变量表,操作数栈,动态链接,方法出口等信息. 每一个方法从调用直至执行完成

jvm系列(二):JVM内存结构

原文出处:纯洁的微笑 所有的Java开发人员可能会遇到这样的困惑?我该为堆内存设置多大空间呢?OutOfMemoryError的异常到底涉及到运行时数据的哪块区域?该怎么解决呢?其实如果你经常解决服务器性能问题,那么这些问题就会变的非常常见,了解JVM内存也是为了服务器出现性能问题的时候可以快速的了解那块的内存区域出现问题,以便于快速的解决生产故障. 先看一张图,这张图能很清晰的说明JVM内存结构布局. JVM内存结构主要有三大块:堆内存.方法区和栈.堆内存是JVM中最大的一块由年轻代和老年代组

JVM学习 - 体系结构 内存模型

一:Java技术体系模块图 二:JVM内存区域模型 1.方法区 也称"永久代" ."非堆",  它用于存储虚拟机加载的类信息.常量.静态变量.是各个线程共享的内存区域.默认最小值为16MB,最大值为64MB,可以通过-XX:PermSize 和 -XX:MaxPermSize 参数限制方法区的大小. 运行时常量池:是方法区的一部分,Class文件中除了有类的版本.字段.方法.接口等描述信息外,还有一项信息是常量池,用于存放编译器生成的各种符号引用,这部分内容将在类加

JavaScript学习系列之内存模型篇

一个热爱技术的菜鸟...用点滴的积累铸就明日的达人 正文 如果真的想学好一门语言,那么一定要了解它内存模型,本篇文章就带你走进JavaScript的内存模型,由于本人才疏学浅,若有什么表述有误的地方,欢迎各位看官能够指点一二,在此不胜感激... 在阅读这边文章之前,默认您已经掌握了JavaScript的基本概念.栈堆等基本数据结构以及计算机基本理论基础,如有了解欠缺,请移步相关博客后再阅读本文. 一.基本的数据类型的内存结构 首先粗略的介绍一下JavaScript中五种基本的数据类型Undefi

jvm(12)-java内存模型与线程

[0]README 0.1)本文部分文字描述转自“深入理解jvm”,旨在学习“java内存模型与线程” 的基础知识: [1]概述 1)并发处理的广泛应用是使得 Amdahl 定律代替摩尔定律称为计算机性能发展源动力的根本原因: 2)Amdahl 定律:该定律通过系统中并行化与串行化的比重来描述多处理器系统能获得的运算加速能力: 3)摩尔定律:该定律用于描述处理器晶体管数量与运行效率间的发展关系: Conclusion)这两个定律的更替代表了近年来硬件发展从追求处理器频率到追求多核心并行处理的发展

JVM原理与内存模型

编译型语言:一次性地编译成机器码,生成可执行文件.解释型语言:使用专门的解释器对源码逐行解释成特定平台的机器码并立即执行的语言. JVM原理:Java语言既是编译型语言,又是解释型语言:Java源码通过javac命令被编译成.class文件,这种字节码文件不面向任何平台,只面向JVM(Java Virtual Machine):JVM是Java跨平台的关键部分,其向上提供给Java字节码程序的接口完全相同,而向下适应不同平台的接口则互不相同,为特定平台提供特定机器码,使用java命令解释执行.

jvm 03-java堆内存模型

java中最大的特点在于其具备良好的垃圾收集特性 GC是整个java之中最重要的安全保证 整个JVM中的GC的处理机制:对不需要的对象进行标记,而后进行清除 JVM堆内存划分 在JDK1.8之后,将最初的永久带内存空间取消了,该图为JDK1.8之前的内存空间组成 取消永久代目的是为了将HotSpot于JRockit两个虚拟机标准联合为一个 在整个JVM堆内存之中实际上将内存分为了三部分: 新生带(年轻代):新对象和没达到一定年龄的对象都在年轻代 老年代:被长时间使用的对象,老年代的内存空间应该要

[转]JVM系列二:GC策略&内存申请、对象衰老

原文地址:http://www.cnblogs.com/redcreen/archive/2011/05/04/2037056.html JVM里的GC(Garbage Collection)的算法有很多种,如标记清除收集器,压缩收集器,分代收集器等等,详见HotSpot VM GC 的种类 现在比较常用的是分代收集(generational collection,也是SUN VM使用的,J2SE1.2之后引入),即将内存分为几个区域,将不同生命周期的对象放在不同区域里:young genera

JVM系列二:GC策略&内存申请、对象衰老

JVM里的GC(Garbage Collection)的算法有很多种,如标记清除收集器,压缩收集器,分代收集器等等,详见HotSpot VM GC 的种类 现在比较常用的是分代收集(generational collection,也是SUN VM使用的,J2SE1.2之后引入),即将内存分为几个区域,将不同生命周期的对象放在不同区域里:young generation,tenured generation和permanet generation.绝大部分的objec被分配在young gener

jvm系列 (二) ---垃圾收集器与内存分配策略

回顾 上文介绍了jvm的内存区域以及介绍了内存的溢出情况. jvm区域分为5个,线程独有:虚拟机栈,本地方法栈,程序计数器.线程共享:方法区,堆 两种溢出:栈溢出(StackOverflowError),OutOfMemoryError(OOM) 为什么学习垃圾收集 看起来jvm好像一切帮你做好,但是当垃圾收集成为系统达到更高并发量的瓶颈时,我们就需要对这种自动化的技术进行监控和调节. 根据实际应用需求,选择最优的收集方式才能更高的性能. 垃圾收集的区域 虚拟机栈,本地方法栈,程序计数器是线程私