Java内存区域划分及对象的访问方式

JVM 内存区域划分


JVM 内存区域划分如图:

这里写图片描述

下面对以上划分具体讲解:


  • 程序计数器

程序计数器用来指示当前字节码执行到第几行。每个计数器只能记录一个线程的行号,所以他是线程私有的。
当程序执行Java方法时,其记录当前执行指令地址;
当执行本地(native,使用c语言编译)方法时,其值为 Undefined
由于其单一功能,它是唯一一个没有内存溢出(OutOfMemoryError)的区域.


  • 虚拟机栈

一个线程的每一个方法在执行的同时,都会在虚拟机栈创建对应的栈帧。方法的调用和完成对应着栈帧在虚拟机栈中的入栈与出栈。

   栈帧 :栈帧中存储方法的局部变量表,操作站,动态链接,方发出口等内容。

   局部变量表 :存放方法的局部变量(基本数据类型,对象的引用 reference ,返回地址等)
其中只有 longdouble 占用两个局部变量空间(slot),其他都是一个局部变量空间。
局部变量表在编译时就已经确定,方法运行所需要分配的空间在栈帧中完全确定,在方法的整个生命周期都不会发生改变。

   局部变量空间 slot:对于32位机器,1 slot = 32 bit

   异常:当请求栈深度大于JVM允许栈深度时,抛出 StackOverFlowError(栈溢出)异常;由于栈深度可动态改变,直至内存不足时会抛出 OutOfMemoryError(内存溢出)异常

  每个线程都对应一个虚拟机栈,因此也是线程私有的。


  • 本地方法栈

   同上,唯一区别是本地方法栈执行 native 方法。


  • 堆区(Heap)

   是JVM中最重要最大的区域。所有线程共享。用来存储对象实例。会抛出OutOfMemoryError:Iava heap space(内存溢出)异常


  • 方法区(Method Area)

   方法区在JDK1.6版本HotSpot虚拟机中被设计为永久代,可能会在后续设计中取消。

   方法区用来存储虚拟机加载的类信息(版本,field,方法,接口等),静态变量,编译器即时编译代码等。

   对方法区的垃圾回收操作主要集中在对常量池的内存回收以及对已加载类的卸载。

   会抛出OutOfMemoryError:PermGen space(内存溢出)异常

运行时常量池(Runtime Constant Pool)

   1. 存储编译期就生成的字面常量,符号引用,翻译后的直接引用。

      符号引用:编码是用字符串表示某个变量,接口的位置等

      直接引用:经过翻译的地址。在类链接阶段完成翻译

   2. 存储运行时产生的常量,比如 String.intern()方法,该方法判断常量池中有没有已存在的字符串常量,没有则新建,有则返回地址。


  • 直接内存

   JDK基于通道(Channel)和缓冲区(Buffer)的内存分配方式。假设机器有4G内存,1G被JVM占用,则剩余3G为直接内存。


JVM中对象访问方式

   以Object obj = new Object()为例:Object obj 作为一个本地引用(reference)存储在虚拟机栈中的本地变量表中。

   new Object() 作为对象实例存储在堆中。Object类的类型信息数据存储在方法区中。

   常见的对象访问有两种:

   1. 句柄访问

      如下图所示:

      这里写图片描述

   在这种访问方式中,JVM堆中会有专门的一块区域作为句柄池。这种方法的优点是稳定

   2. 直接指针访问

      如下图所示:

      这里写图片描述

   此种方式中,JVM堆中存储的对象信息包含了在方法区中相应的类型数据地址。其优势在于速度快。而在HotSpot虚拟机中就用的这种方式。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值