java虚拟机内存分布

来源:互联网 发布:java hash算法原理 编辑:程序博客网 时间:2024/06/04 23:20

概括

java虚拟机在运行的时候,会把内存划分成若干个内存块、这些区域各自有各自的作用用途 。


1.程序计数器


程序计数器是一块比较小的内存区域,它可以看做是当前线程所执行的字节码的行号指示器。字节码指示器工作的时候就是通过这个指令来获取下一条需要执行的指令。(分支,循环,判断、异常等都需要这个计数器来完成)

线程之间的指令是互不干影响的。通常称之为“线程私有”的内存


2.java虚拟机栈

和程序计数器一样,java虚拟机栈也是线程私有的。它的生命周期和线程一样。它描述的是java方法执行的内存模型。

每个方法在执行的时候都会创建一个栈帧,意味着每个方法从调用到执行完成都对应着一次入栈和出栈的过程。

存储基本类型,对象引用,返回地址类型

如果线程请求的栈的深度大于虚拟机的锁允许的深度。将会抛出stackoverflowError。

如果虚拟机可以支持动态的扩容,如果申请时失败,将会抛出outofMemoryError异常


3.本地方法栈

本地方法栈和java虚拟机栈极其类似,只是本地方法使用到的是native方法服务。有的虚拟机(比如sun hotspot)直接将本地方法栈和java虚拟机合二为一。

和java虚拟机方法一样也会抛出stackoverflowError和 outofMemoryError异常


4.java堆

对于大多java应用来说,java堆是java内存中使用最大的一块。java堆是所有线程共享的一块区域。主管区域唯一的目的就是存放java对象的实例和java数组。

随着JIT编译器的发展和逃逸分析技术。java虚拟机规范中也明确提出所有的对象都在java对中分配已经不是那么“绝对”了;


java堆是java垃圾回收主要的区域。因此很多时候也被称之为“GC堆”。从内存回收的角度来看,由于现在主流的基本都采用分代收集算法,所以java堆中还可以分为

新生代和老年代。在细致一点有:eden空间,from survivor和to survivor等空间。

根据java虚拟机规范:物理上java堆是可以不连续的、只要逻辑上连续既可。一般可以通过-Xmx 和 -Xms来控制。

如果堆中没有内存分配实例并且堆也无法在扩展、将会抛出OutofMemoryError异常。


5方法区

方法去和java对一样是线程共享区域。它用于存储已经被虚拟机加载的类信息。常量,静态变量,等数据。虽然java虚拟机把方法区描述为java堆的一个逻辑分区。

但是它却有一个名称(非堆)。

对于hotspot来说(其它的虚拟机不存在永久区这个概念),很多人都愿意把方法区称之为永久代.因为hotspot使用永久带来实现了方法区。这样垃圾回收就可以像

管理java堆一样来管理该区域。

但是使用永久代容易造成内存溢出(-XX:MaxpermSize限制)


6.运行时常量池

运行时常量是方法去的一部分。class文件除了有类的版本,字段,方法,接口等描述,还有一项信息是常量池。用于存放编译期生成的各种字面常量和符号引用。这部分

内容将在类加载后进入方法区的运行期常量存放。



7直接内存

直接内存并不属于java虚拟机运行时的一部分。也不是java虚拟机规范中定义的区域。

在java1.4之后的NIO中,引入了通道和缓冲区的概念。它可以使用native函数库直接分配堆外内存。然后通过一个存储在java堆中的DirectByteBuffer对这块内存

操作。这样可以让引用在一些场景中性能得到提升。避免了java堆和native中来回的复制数据。
























0 0