java运行时的内存区域

1.概述

java虚拟机在执行java程序的过程中会把它所管理的内存划分为若干个不同的数据区域。
这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有些区域则依赖用户线程的启动和结束而建立和销毁。
java虚拟机所管理的内存包括以下几个运行的数据区域,如图

2.各区域描述

1) 程序计数器

程序计数器是一块较小的内存空间,可以看作当前线程所执行的字节码的行号指示器,字节码解释器工作时,就是通过改变这个计数器的值来选择下一条需要执行的字节码的指令,相当于汇编语言中的cs:ip。
java虚拟机的多线程是通过并发来实现的,所以在任何一个确定的时刻内,一个处理器只能够执行一条线程中的指令,所以为了保证线程的切换不会改变每一个线程执行的位置,每一条线程都有一个独立的程序计数器,即程序计数器是线程私有的。这个内存区域的生命周期就是线程的生命周期。
注意:如果线程正在执行的是一个java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是Native本地方法,那么这个计数器值为空(undefind)。

2) java虚拟机栈

java虚拟机栈是线程私有的,它的生命周期与线程相同。虚拟机栈描述的是java方法的内存模型:每个方法在执行时会创建一个栈帧,用于存储局部变量表,操作数栈等信息,每一个方法从调用到执行完成的过程就对应着一个栈帧从入栈到出栈的过程。
在虚拟机栈中,局部变量表是一个重要的部分,其存放了编译器可知的各种基本数据类型,对象引用类型,returnAddress类型(指向一条字节码指令的地址),局部标量表中的内存空间在编译期间完成分配,在方法运行期间不会改变局部变量表的大小。

3) 本地方法栈

本地方法栈与虚拟机栈十分相似,区别在于:虚拟机栈为虚拟机执行java方法(字节码)服务,本地方法栈为虚拟机使用到的Native方法服务。

4) java堆

一般而言,java堆(java heap)是虚拟机所管理的内存中最大的一块。java堆是被所有线程所共享的一块内存区域,在虚拟机启动时创建。其唯一的用于存放对象实例,几乎所有的对象实例都在这里分配内存。
java堆也是垃圾收集器管理的主要区域。从内存回收的角度看,java堆可以细分为新生代和老年代,也可在细致的分下去;从内存分配的角度看,线程共享的java堆中可能划分出多个线程私有的分配缓冲区(Thread Local Allocation Buffer,TLAB)。
java堆可以处于物理上不连续的内存空间,只要逻辑上是连续的即可。

5) 方法区

方法区也是各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息,常量,静态变量,即时编辑器编译后的代码等数据。·

6) 运行时常量池

运行时常量池是方法区的一部分。class文件中的常量池,用于存放编译期间生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池存放。

7) 直接内存

直接内存并不是虚拟机运行时数据区的一部分,也不是java虚拟机规范中定义的内存区域,但是这部分内存也会被频繁使用,可能导致OutOfMemoryError异常出现。

本博文完全参照《深入理解java虚拟机》(周志明),属于笔记整理。

posted @ 2019-02-19 15:57  Mrfanl  阅读(515)  评论(0编辑  收藏  举报