深入理解java虚拟机(第二版)——第二章:java内存区域与内存溢出异常

一、运行时数据区域

java虚拟机在执行java程序时会把它所管理的内存划分为若干个不同的数据区域。这些区域都有各自的用途,以及创建和销毁时间,有些区域随着虚拟机进程的启动而存在,有些区域则依赖用户县城的启动和结束而建立和销毁。根据《java虚拟机规范(javaSE7版)》规定,java虚拟机所管理的内存将会包括以下几个运行时数据区域:

                                                           

1.1 程序计数器

程序计数器时当前线程所执行的字节码的行号计数器,字节码解释器在通过改变这个计数器的值来选取下一条待执行的字节码指令。java虚拟机的多线程通过线程轮流切换并分配处理器执行时间的方式来实现,在任何一个时刻,一个处理器只会执行一条线程中的指令。因此,程序计数器能保证线程在切换后能恢复到正确的执行位置。程序计数器为线程私有,称为线程私有内存。

线程执行java方法,程序计数器正常保存为执行方法的字节码地址,如果执行Native方法,则程序计数器为空(undefined)。程序计数器是java虚拟机中没有规定任何OutOfMemoryError情况的区域。

1.2 java虚拟机栈

该内存为线程私有,生命周期与线程相同。虚拟机栈描述的是java方法执行的内存模型。虚拟机栈描述了java方法执行的内存模型:每个方法在执行时都会创建一个栈帧,用于存储局部变量表,操作数栈,动态链接,方法出口等信息。每个方法从调用至执行完成的过程对应着一个栈帧在虚拟机栈中入栈到出栈的过程。

局部变量表存放了编译期可知的各种基本数据类型:boolean, byte, char, short, int, float, long, double,对象引用(reference类型)和returnAddress类型。局部变量表内存空间在编译期间完成分配,当进入一个方法时,这个方法在栈帧中分配多大空间是完全确定的,运行期间不会改变局部变量表的大小。

1.3本地方法栈

与虚拟机栈作用类似,只不过本地方法栈为Native方法服务,在虚拟机规范中对本地方法栈中方法使用的语言,使用方式和数据机构没有强制规定,虚拟机可以自由实现。

1.4java堆

java堆是java虚拟机中内存最大的一块。java堆非线程私有,被线程所共享。在虚拟机启动时创建。细腻及规范规定:所有的对象实例和数组都要在堆上分配内存。线程私有的程序计数器和虚拟机栈等内存区域会随着线程的终止而销毁,因此一般来说GC的主要区域在堆区。堆区根据对象实例的存活时间分为了Eden空间,From Survivor空间和To Survivor空间。

线程共享的堆区存在着线程私有的分配缓冲区(Thread Local Allocation Buffer,TLAB),该区域可以手动关闭。

1.5方法区

为线程共享区域,存放已被虚拟机加载的类信息,常量,静态变量,即时编译后的代码等数据。细虚拟机规范把方法区描述为堆得一个逻辑部分。虚拟机规范该区域可以不实现垃圾收集。该区域的回收主要为常量池的回收和类型卸载,结果往往事倍功半。

Class文件除了有类的版本,字段,方法,接口等描述外,还有常量池,储存编译期生成的各种字面量和符号引用。class文件常量池将在类加载后进入方法区的运行时常量池。运行时常量池内容包括:

  1. class文件常量池
  2. class文件常量池里面的符号引用翻译出的直接引用

运行时常量池相对class文件常量池具备动态性,也就是并非只有class文件的常量池的内容才能进入方法区的运行时常量池,运行期间也可以将新的常量放入池中。

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值