java虚拟机学习笔记一

来源:互联网 发布:ios kvo监听数组变化 编辑:程序博客网 时间:2024/05/29 10:31

运行时数据区

java虚拟机在执行java程序时会将管理的内存分为不同的区域,根据jvm规范一共分为5个区域,如下图。
)

  • 程序计数器

    1. 线程私有的,生命周期与线程一致
    2. 独立存储,互相隔离
    3. 存储的字节码指令的地址,字节码解释器通过程序计数器来选取下一个需要执行的指令
    4. 不会有OutOfMemoryError异常的情况
  • java虚拟机栈

    1. 线程私有的,生命周期与线程一致
    2. 独立存储,互相隔离
    3. 每一个方法被调用到完成的过程就是栈帧在java虚拟机栈中入栈到出栈的过程
    4. 存储编译期可知的局部变量表(基本数据类型,对象引用reference和returnAddress类型),操作栈,动态链接,方法出口等信息
    5. 超出栈深度StackOverflowError,栈动态扩展无法申请内存空间OutOfMemoryError
  • 本地方法栈
    本地方法栈与java虚拟机栈很相似,其区别不过是本地方法栈是为Native方法服务的。

    1. 线程共享区域
    2. 虚拟机启动是创建
    3. 存放对象实例
    4. 可细分为新生代和老年代,在细致一点可以分为Eden空间,From Survivor空间,To Survivor空间等。
    5. 堆内存可以是物理上不连续的内存空间,只要逻辑上是连续的即可。可以通过-Xmx和-Xms控制堆大小。
    6. 如果堆内没有内存来分配对象实例,并且再也无法扩展时,抛出OutOfMemoryError
  • 方法区
    1. 线程共享
    2. 存储已被虚拟机加载的Class信息,如类名,访问修饰符,常量池,字段描述,方法描述等。
    3. 堆内存可以是物理上不连续的内存空间,只要逻辑上是连续的即可。
    4. 抛出OutOfMemoryError
    5. 可通过-XX:PermSize 和 -XX:MaxPermSize 来限制方法区的大小。

直接内存

直接内存并不是虚拟机运行时数据区的一部分,也不是java虚拟机所定义的。
在jdk1.4新加入的NIO类,引入了一种基于通道(channel)与缓存区(buffer)的I/O方式,它可以直接使用Native函数库直接分配堆外内存,然后通过一个存储在java堆里的DirectByteBuffer对象作为这块内存的引用操作。这样能在一些场景显著提高性能,因为避免了在java堆和Native堆中来回复制数据。虽然这块内存不是虚拟机直接管理,但如果超过了本机物理内存的大小也会抛出OutOfMemoryError。

对象访问

在java虚拟机中,Object obj = new Object()这段代码在创建对象的时候是如何分配内存的呢?“Object obj”这部分语句定义将会反映到java虚拟机栈的局部变量表中,作为一个reference类型数据出现。而“new Object()”这部分语句定义将会反映到java堆中,形成一块存储了Object类型的所有实例数据值的结构化内存。另外,在java堆中还必须包含能查找到此对象类型数据(如对象类型,父类,实现的接口,方法等)的地址信息,这些类型数据则存储在方法区中。
这里写图片描述

0 0
原创粉丝点击