登录
    Technology changes quickly but people's minds change slowly.

深入理解java 虚拟机(一)

技术宅 破玉 1166次浏览 0个评论

Java虚拟机内存区域划分

  运行时数据区主要包含 程序计数器、java 虚拟机栈、本地方法栈、堆、方法区 这几部分。
   程序计数器可以看做是当前线程所执行的字节码指示器的行号。每个线程都有一个独立的程序计数器,各个线程之间计数器互不影响,独立存储,因此程序计数器是线程私有的。如果计数器执行的是java方法,这个计数器记录的是正在执行的虚拟机字节码指令地址,如果执行的是Native方法,这个计数器则为空。此内存区域是java虚拟机规范中唯一一个没有规定任何OutOfMemoryError 的区域。
   java 虚拟机栈,和程序计数器一样也是线程私有的,生命周期和线程相同。每个java方法执行时都会创建一个栈帧 用于存储局部变量表、操作数栈、动态链接、方法出入口等信息,每个方法从调用直至执行完成,就对应一个栈帧在虚拟机栈中从入栈到出栈的过程。局部变量表存放的编译期可知的各种基本数据类型、对象引用、returnAddress 类型。Java虚拟机规范中,对这个区域规定了两种异常状况: 如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverFlow 异常;如果虚拟机栈可以动态扩展,如果扩展时无法申请到足够的内存,就会抛出 OutOfMemoryError 异常
   本地方法栈,与虚拟机栈的区别就是,虚拟机执行 java 方法,本地方法栈执行的 Native 方法服务。与虚拟机栈一样,本地方法栈也会抛出StackOverFlow 和OutOfMemoryError 异常。
  java 堆,这是java 虚拟机所管理的内存中最大的一块。java 堆是所有线程所共享的一块区域,在虚拟机启动时创建,此内存区域的唯一目的是存放对象实例,几乎所有的对象都在这里分配内存。Java堆还可以细分为新生代和老年代,再细致还有Eden空间、From survivor 空间、To survivor 空间,java 堆可以设置成固定大小 也可以设置为可扩展的,主流虚拟机都是通过实现为可扩展的(通过 -Xms 和 -Xmx) 来控制,如果在堆中没有内存完成实例分配,并且堆也无法再扩展,将会抛出 OutOfMemoryError 异常。
   方法区与java 堆一样,是各个线程共享的内存区域,用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。当方法区无法满足内存分配需求时,将抛出OutOfMemory Error异常。
  运行时常量池是方法区的一部分。Class 文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项是常量池,存放各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池存放。也就由方法区决定,当常量池无法再申请到内存时就会抛出OutOfMemoryError 异常。
  直接内存(物理机内存)不是虚拟机运行数据区的一部分,也不是java虚拟机规范中定义的内存区域,但是这部分 内存也被频繁使用,也可能导致OutOfMemoryError 异常。


华裳绕指柔, 版权所有丨如未注明 , 均为原创|转载请注明深入理解java 虚拟机(一)
喜欢 (0)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址