深入理解java虚拟机笔记(1)java虚拟机内存划分

一、java虚拟机内存划分

 

 

1.1.程序计数器

程序计数器是当前线程执行的字节码的行号指示器,字节码解释权通过改变这个计数器的值来选取下一条需要执行的字节码指令。它是程序控制流的指示器,分支、循环、跳转、异常处理,线程恢复都需要依赖这个计数器完成。

每个线程都有一个独立的程序计数器,独立存储、互不影响。

1.2.java虚拟机栈

java虚拟机栈也是线程私有的,它的生命周期与线程相同。

虚拟机栈描述的是java方法执行时的内存模型。每个java方法执行时,java虚拟机都会同步创建一个栈帧,用于存储局部变量表、操作数栈、动态连接、方法出口等信息。

每一个方法从执行到执行结束的过程,就对应一个栈帧从入栈到出栈的过程。

局部变量表存储了编译器可知的各种java虚拟机基本数据类型、对象的引用类型和returnAddress类型(一条字节码指令的地址)。其中long和double会占用两个局部变量槽slot,其他的都占用一个。

如果线程请求的栈深度大于虚拟机运行的深度,就会抛出StackOverflowError ,如果虚拟机栈申请不到足够的内存,就会抛出OutOfMemoryError 。

1.3.本地方法栈

本地方法栈实现原理与虚拟机栈相同,不过是用来专门执行本地方法的。

1.4.java堆

java堆是虚拟机管理的内存中最大的一块。被所有线程共享。在虚拟机启动时创建,用于存放java对象。

java堆是垃圾收集器管理的内存区域。现代虚拟机大部分根据分代收集理论设计,对于堆内存的分配,Java虚拟机都是按照可扩展来实现的(通过参数-Xmx和-Xms设定) 。 如果在Java堆中没有内存完成实例分配, 并且堆也无法再扩展时, Java虚拟机将会抛出OutOfMemoryError异常

1.5.方法区

虽然叫方法区,但这里面存的却不是方法!

方法区域java堆一样,由多个线程共享,它用于存储被java虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。如果方法区无法满足新的内存分配需求时, 将抛出OutOfMemoryError异常。

运行时常量池是方法区的一部分。class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池表,用于存放编译器生成的各种字面量和符号引用。这部分内容在类加载后放在运行时常量池中。

常量池无法再申请到内存时会抛出OutOfMemoryError异常

1.6.直接内存

直接内存(Direct Memory) 并不是虚拟机运行时数据区的一部分, 也不是《Java虚拟机规范》 中定义的内存区域。 但是这部分内存也被频繁地使用,在JDK 1.4中新加入了NIO类, 引入了一种基于通道(Channel) 与缓冲区 (Buffer) 的I/O方式,它可以使用Native函数库直接分配堆外内存, 然后通过一个存储在Java堆里面的DirectByteBuffer对象作为这块内存的引用进行操作。 这样能在一些场景中显著提高性能, 因为避免了在Java堆和Native堆中来回复制数据。

posted @ 2022-03-16 15:26  Mars.wang  阅读(62)  评论(0编辑  收藏  举报