JVM内存区域

(一)   程序计数器(program counter register线程私有)

当前线程执行字节码的行号指示器

1. 分支、循环、跳转、异常处理、线程恢复等依赖计数器完成

2. 当执行的是native方法时,值为空

3. Jvm中唯一没有内存溢出的

(二)   Java虚拟机栈(Java virtual machine stacks线程私有)

Java方法执行的内存模型,用于存储局部变量表、操作栈、动态链接、方法出口等信息。

1. 大多Java程序员说的栈可能指局部变量表,用于存放基础数据类型、对象引用、一条字节码指令地址

1)      局部变量表所需内存空间在编译时完成分配,且大小确定,运行时不会改变,处理longdouble占两个其他基础数据类型只占一个变量空间

2)      基础数据类型:booleanbytecharshortintfloatlongdouble

3)      对象引用:基于虚拟机实现,可以是指向对象起始地址的引用指针、也可以是代表对象的句柄或其他与对象位置相关的信息

2. 这区域有两种异常

1)       StackOverflowError(不可以动态拓展jvm):栈深度大于虚拟机允许深度

2)      OutOfMemoryError(动态拓展的jvm):超出最大可拓展内存

(三)   本地方法栈(native method stacks

与虚拟机栈类似(有虚拟机把两者合二为一),不过虚拟机栈为jvm执行Java方法服务,而本地方法栈为jvm使用到的native方法服务。

(四)   Java堆(Java heap线程共享)

jvm启动时创建的最大一块用于存放对象实例,数组,常量池,静态变量等

1.      常量池,静态变量在jdk1.8之前存储在方法区

2.      常量池:类用到的常量的有序集合,包含直接常量(stringinteger,和float常量)和对其他类型,域和方法的符号引用

l   Jvm为每个被装载的类维护一个常量池

l   直接常量存储在一张固定长度表,如string类型存储在CONSTANT_String_info

3.      静态变量:

l   所有实例共享,即使没有实例也可以访问

l   只与类相关,在方法区中是类逻辑上的一部分

l   Jvm必须在方法区中为每个non-final类变量分配空间(存储在声明的类信息内)

4.      常量:使用final修饰的变量

l   每个常量都会在常量池中有一个拷贝

l   Final变量存储在所有使用它的类信息内(注意与non-final的区别)

5. 物理上不连续,逻辑上连续

6. 也被称为GC堆(garbage collector heap)垃圾收集器管理的主要区域

7. 可以通过-Xmx-Xms配置

8. 内存不足时有OutOfMemoryError异常

(五)   方法区(method area线程共享)

存储被jvm加载的类信息,即时编译后的代码数据等

1.      Jdk1.8之前使用jvm内存“永久代”(PerGen)区域,1.8使用元空间(MetaSpace)实现,且不使用jvm内存而是使用系统内存

2.      类基本信息

l   类的完整有效名(如java.lang.Object,具体保存形式根据方法区实现不同而不同)

l   类的直接父类的完整有效名(若是object则不记录

l   类的修饰符(publicabstractfinal等)

l   类的直接接口的有序列表

3.      域信息(field

l   域名

l   域类型

l   域修饰符(publicprivateprotectedstaticfinalvolatiletransient的某个子集)

4.      方法信息(method

l   方法名

l   方法返回类型

l   方法参数数量和类型(有序)

l   方法的修饰符(publicprivateprotectedstaticfinalsynchronizednativeabstract的一个子集)

l   除了nativeabstract以外其他方法还保存方法的字节码操作数栈和方法栈帧的局部变量区的大小

l   异常表

5.      Java堆一样不需要连续内存,可以选择固定大小或可扩展,也可以选择不实现垃圾收集

6.      内存不足时有OutOfMemoryError异常

posted @ 2019-07-05 22:55  爱上咖啡的唐  阅读(191)  评论(0编辑  收藏  举报