美文网首页
java运行时数据区域

java运行时数据区域

作者: f1zz | 来源:发表于2018-07-19 17:29 被阅读0次

java不像c语言一样,需要手动分配和释放内存,java的内存管理都是由jvm自动处理的,那么是不是我们就不需要了解java的内存管理了呢?不,机器处理并不能保证避免内存泄露和溢出的出现,因此学习好内存管理是我们解决内存泄露和溢出等问题的知识基础。第一步先来学习运行时数据区域。
如下图,这是jvm对管理的内存的一个划分,分为方法区、堆、虚拟机栈、本地方法栈和程序计数器这五个区域,每个区域有着自己的用途,他们创建和被销毁的时间也不同。


runtime_area.png

程序计数器(program counter register)

  • 线程私有的一块内存空间,每个线程各有一个程序计数器,互不影响。
  • 可以看作当前线程执行的字节码的行号指示器,字节码解释器通过程序计数器来获取下一条需执行的字节码指令,分支、循环、跳转、异常处理、线程恢复都离不开这个计数器
  • 若执行java方法,计数器记录字节码指令的地址;若执行native方法,计数器则为空
  • 此内存区域是唯一没OutOfMermoryError的区域

虚拟机栈

  • 线程私有的,生命周期和线程相同
  • 每个方法都会创建一个栈帧来存储局部变量表、操作数栈、动态连接、方法出口等信息。其中局部变量表存放了编译期可知的基本数据类型和对象引用(不是对象)
  • 局部变量表在编译期就会完成内存分配,因此在运行期局部变量表的大小时固定的
  • 若请求的栈的大小超过虚拟机允许的最大内存,就会抛出StackOverFlowException异常;若虚拟机栈可以动态扩展,扩展时无法申请到足够的内存,会抛出OutOfMermoryError异常

本地方法栈

  • 与虚拟机栈类似,有的虚拟机(如 sun Hotspot虚拟机)将本地方法栈和虚拟机栈合二为一
  • 本地方法栈为native方法服务,而虚拟机栈为java方法服务
  • 会出现的异常和虚拟机栈一样

  • 所有线程共享的最大的一块内存。
  • 在虚拟机启动时创建,可通过jvm参数 -Xmx和-Xms 来设置堆内存大小
  • 几乎所有的对象实例和数组都在堆上存放。逃逸分析这一技术则使得对象不尽都分配在堆上
  • 堆进一步划分可分为新生代和老年代,新生代又可分为Eden空间、From Survivor和To Survivor。这些划分都是为了 GC(garbage collection),后面会讲到GC

方法区

  • 线程共享
  • 存储虚拟机加载的类信息、常量、静态变量和即时编译器编译后的代码等数据
  • 当方法区无法满足内存分配的需求时,会抛出OutOfMermoryError异常

运行时常量池

  • 运行时常量池jdk1.6包括1.6之前位于方法区,1.7以后位于堆中
  • class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后存放于方法区的运行时常量池。
  • 具有动态性。也可在运行期中加入运行时常量池,如String的intern方法。
  • 内存不够时会抛出OutOfMermoryError异常

直接内存

  • 并不是虚拟机规范中定义的区域,但被频繁使用,也可能出现OutOfMermoryError异常
  • JDK1.4引入了NIO,引入了一种基于通道和缓冲区的IO方式,可以使用native函数库分配堆外内存,java堆可以通过DirectByteBuffer对象来操作这块内存,提高了性能。
  • 受本机内存限制,有时忽略了这块内存,导致各内存区域大于物理内存限制,从而出现OutOfMermoryError异常

相关文章

网友评论

      本文标题:java运行时数据区域

      本文链接:https://www.haomeiwen.com/subject/xmotmftx.html