您的位置:首页 > 编程语言 > Java开发

JVM1

2016-04-14 14:10 387 查看

Java虚拟机内存区分布概要

计数器(program counter register)

计数器是内存中分配的较小的内存空间,可以看成当前线程执行字节码的型号指示器,字节码解释器通过改变计数器的值来选取下一条需要执行的字节码指令。(分支,循环,跳转,异常处理,线程回复等)

java多线程,是通过线程切换与分配处理时间方式实现,为了线程切换后能回复到正确执行位置,需要一个独立的计数器,各线程之间计数器互不影响,计数器内存区域也被称为“线程私有”内存

一个线程在执行java方法,计数器记录的是正在执行的虚拟机字节码指令地址。计数器内存区域是唯一没有OOM情况的区域

虚拟机栈与本地方法栈

虚拟机栈是描述java方法执行的内存模型。一个方法执行的时候,会创建一个栈帧,栈帧是用来存储局部变量表,操作数栈,动态链接,方法出口(方法执行结束返回标识该方法执行地址的标记)。

局部变量表存放了各种基本类型,所需要的内存空间是在编译期间就完成分配,并且大小是固定的,方法运行的时候,不会改变局部变量表的大小。

虚拟机栈异常:请求深度大于虚拟机允许抛出stackverflowError ,如果动态扩展申请不到足够的内存抛出OOM 。其实两种情况实际都是一件事, 实际应用过程中,栈内存溢出都只会抛出前一个异常。

线程私有的,生命周期与线程相同

Java堆(GC主要管理区域)

此内存区,唯一目的就是存储java对象实例

该内存区是垃圾收集的主要区域,按照收集器分代收集算法,该区域可以细分为新生代,老年代。新生代又细分为Eden,from survivor,to survivor。默认比例为8:1:1

假设对象在Eden,from中产生。如果GC一次之后,该对象还存活,则将该对象移入to中。以后每次GC,如果存活则age +1.默认age=15则移入老年代。

大对象应该是直接存储在老年代中的。

-Xms -Xmx设定最小内存与最大内存空间,如果没有足够空间完成实例分配,抛出oom异常。两个参数一般设置为一致,以避免每次垃圾回收完成后JVM重新分配内存。

该内存区是线程共享的

方法区与运行时常量池

方法区主要存储已经被虚拟机加载的类的信息,常量,静态变量,即时编译器编译后的代码。在java虚拟机规范中把方法区描述为堆的逻辑部分,有一个别名叫Non-Heap 与java堆做区分。

运行时常量池是方法区一部分,运行时常量池区分常量池是具备了动态性,运行期间,也可以设置常量,String intern()方法,如果常量表中没有该记录,则添加记录,并且返回引用地址,如果已经存在,则返回存在的引用地址。

无法满足内存分配抛出oom异常

该区是线程共享的

直接内存

直接内存不是虚拟机运行时数据区一部分,也不是java虚拟机规范中定义的内存区域,但是这部分内存也被频繁调用,同样可能出现oom异常,nio可以直接使用native函数库直接分配堆外内存,通过java堆中的DirectByteBuffer对象作为这一块内存的应用进行操作,避免了java堆与native堆中来回复制数据。

设置-Xmx等参数的时候,总和要小于物理内存,不然堆外内存空间不足,造成oom。

对象的创建过程(初解)

对象创建所需要的内存的大小在类加载完成后就可以确定,虚拟机给对象分配内存有两种方式:指针碰撞与空闲列表。

虚拟机创建对象过程需要在虚拟机中分配空间,因此创建对象过程不是线程安全的,解决方法有两种:CAS+失败重试;本地线程分配缓冲(TLAB:预先给每一个线程分配一小块内存)

对象内存布局

对象在内存中分为三部分:对象头(header),实例数据(Instance Data),对其填充(padding)

对象头包含两个部分:(1)自身运行时数据(hashcode(25),age(4),锁状态标示(2)等);(2)类型指针,确定该对象是属于哪一个类的实例

实例数据部分是对象真正存储的有效信息,也就是在代码中定义的各种类型的字段的内容。存储顺序是收到虚拟机分配策略影响的。

填充区没有任何意义,只是保证对象大小是8的倍数。

对象访问定位

java程序需要操作栈上的reference数据操作堆上的具体对象,目前主流的访问方式有:句柄访问,直接指针

句柄访问,java堆中有一块内存叫做句柄池,存放了对象的句柄地址,包含对象的实例数据指针与对象类型指针。

直接指针,java堆在对象创建过程中,包含了对象类型信息。reference直接存储对象实例地址,这样访问速度更快。hotspot使用的是直接指针方式

OutOfMemoryError异常

java堆溢出(-Xms,-Xmx):只要不断创建对象,为了方式对象被回收,将对象存入list中即可抛出oom异常。可以配置-XX:HeapDumpOnOutOfMemoryError虚拟机参数,Dump出当前的内存堆转储快照,便于事后分析。MAT工具(memory analyzer)可以对dump出的文件做分析

虚拟机栈和本地方法栈溢出(-Xss):(1)将局部变量不停增加,超出栈内存(2)大量创建线程。如果栈内存不够,这两种方法都是抛出StackOverflowError。

方法区和运行时常量池溢出(-XX:PermSize -XX:MaxPermSize):List.add(String.value(i++).intern())。方法区存放的是类名,修饰符,常量,字段描述,方法描述等信息,内存溢出的思路是运行时产生大量的类去填充方法区

直接内存溢出(-XX:MaxDirectMemorySize=10M):如果不设置等同于-Xmx.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息