JVM内存结构知识点整理

jvm 内存结构

工作内存模型

jvm内存结构-线程工作角度
此图描述jvm从线程工作角度的一个模型图,主要由两部分组成,工作内存和主存,工作内存为线程栈,主存主要就是堆;

内存结构规范

内存结构规范
注:这只是一个规范,真实情况下不同jvm实现可能些许差异

具体模块介绍

程序计数器
程序计数器是一块较小的内存空间,线程私有存储,字节码的行号指示器,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成。如果正在执行的是Natvie 方法,这个计数器值则为空(Undefined)。此内存区域是唯一一个在Java 虚拟机规范中没有规定任何OutOfMemoryError 情况的区域。
本地方法栈
native方法的线程栈
方法区(non-heap,Permanent区域)
永久带是hotspot关于jvm方法区组成规范的一种实现
在这里插入图片描述
class 区:用于存储已被虚拟机加载的类信息(类元数据)、常量、静态变量、即时编译器编译后的代码等数据。
运行时常量池:存放编译期生成的各种字面量(加载类里面的常量的值)和符号引用(类和接口的完全限定名(Fully Qualified Name)-一种唯一标识、字段的名称和描述符(Descriptor)、方法的名称和描述符),这部分内容将在类加载后存放到方法区的运行时常量池中。
注:动态性:Java 语言并不要求常量一定只能在编译期产生,也就是并非预置入Class 文件中常量池的内容才能进入方法区运行时常量池,运行期间也可能将新的常量放入池中。如String 类的intern() 方法
方法区演变历史
1、HotSpot 虚拟机的设计团队选择把GC 分代收集扩展至方法区,或者说使用永久代来实现,oracle一直要宣称要移出永久带
2、JDK1.6之前string pool位于方法区之中,JDK1.7string pool已经被挪到堆之中。
3、1.8直接移到系统内存中,取名元空间,容量取决于系统内存大小
JDK 1.8 的对 JVM 架构的改造将类元数据(所谓的元数据是指用来描述数据的数据,更通俗一点就是描述代码间关系,或者代码与其它资源(例如数据库表)之间内在联系得数据,对Struts来说就是struts-config.xml,对ejb来说就是ejb-jar.xml和厂商自定义的xml文件,对hibernate来说就是hbm文件。)放到本地内存中,另外,将常量池和静态变量放到 Java 堆里。HotSopt VM 将会为类的元数据明确分配和释放本地内存。
1.8添加元空间的原因
1)字符串存在永久代中,容易出现性能问题和内存溢出。
2)类及方法的信息等比较难确定其大小,因此对于永久代的大小指定比较困难,太小容易出现永久代溢出,太大则容易导致老年代溢出。
3)永久代会为 GC 带来不必要的复杂度,并且回收效率偏低。
4)Oracle 可能会将HotSpot 与 JRockit 合二为一。
Permanent区域初始内存分配
JVM使用-XX:PermSize设置非堆内存初始值,默认是物理内存的1/64;
由XX:MaxPermSize设置最大非堆内存的大小,默认是物理内存的1/4。
线程栈(虚拟机栈)
每当线程调用一个java方法时,JVM就会在该线程对应的栈中压入一个帧
栈帧由三部分组成:局部变量区、操作数栈、帧数据区。
局部变量区大小设置jvm会预先读取方法做判断,一个字长为单位、从0开始计数的数组,类型为short、byte和char的值在存入数组前要被转换成int值,而long和double在数组中占据连续的两项,在访问局部变量中的long或double时,只需取出连续两项的第一项的索引值即可。局部变量区里有方法参数,局部变量,returnAddress 类型(指向了一条字节码指令的地址),非static方法还有this指针(refrence对象)。
操作数栈也是一个字节数组,存放操作操作参数和结果
帧数据区 支持常量池解析、正常方法返回以及异常派发机制。(除了局部变量表和操作数栈,java栈还需要一些数据来支持常量池解析,正常方法返回和异常处理等,大部分java字节码指令需要进行常量池访问,在帧数据区中保存着访问常量池的指针,方便程序访问常量池。
当函数返回或者出现异常时,虚拟机要恢复调用者函数的栈帧,并让调用者函数继续执行下去,对异常处理,虚拟机必须有一个异常处理表,方便在发生异常的时候找到处理异常的代码,因此异常处理表也是帧数据区中重要的一部分)
调用方法是线程栈的变化
在这里插入图片描述
在这里插入图片描述
注:两个栈帧会有一个交集,就是一个方法中调用另一个方法
资料取自:http://blog.csdn.net/f525921307/article/details/51330288

JVM初始分配的内存由-Xms指定,默认是物理内存的1/64;
JVM最大分配的内存由-Xmx指 定,默认是物理内存的1/4。
默认空余堆内存小于40%时,JVM 就会增大堆直到-Xmx 的最大限制,可以由 -XX:MinHeapFreeRatio 指定。
默认空余堆内存大于70%时,JVM 会减少堆直到-Xms的最小限制,可以由 -XX:MaxHeapFreeRatio 指定,
Eden区和2个Survivor区(分别叫from和to),默认比例为8:1
-XX:NewSize和-XX:MaxNewSize
用于设置年轻代的大小,建议设为整个堆大小的1/3或者1/4,两个值设为一样大。
-XX:SurvivorRatio
用于设置Eden和其中一个Survivor的比值,这个值也比较重要。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值