Java虚拟机的内存区域讲解

对于Java来说不容易出现内存泄露和内存溢出的问题,是因为有虚拟机自动内存管理机制,但是一旦出现问题,不了解虚拟机是怎么用内存的,那么排除错误是一件艰难的工作。接下来从概念上了解虚拟机内存的各个区域

分区

java虚拟机在执行Java程序时,会把内存分为方法区,Java虚拟机栈,本地方法栈,Java堆,程序计数器。如图:

程序计数器

顾名思义就是记录当前线程执行到哪一步,等一下CPU回来时可以接着工作。由于单核Java虚拟机的多线程里是通过并发实现,在任何一个确定时刻,只会执行一条线程的指令,为了线程切换之后还能到正确的执行位置。程序计数器时每个线程都有的,不共享,互不影响。这类内存区域为”线程私有“的内存

Java虚拟机栈

与程序计数器一样,这也是线程私有的内存,它的生命周期和当前线程一样。它描述的是java方法执行的内存模型,每个方法执行的同时会创建一个栈帧用于存局部变量,操作数栈,动态链接等信息,每个方法从头到结束对应一个栈帧在Java虚拟机栈中入栈出栈的过程。经常我们说的栈和堆,而栈说的就是这个Java虚拟机栈。

本地方法栈

这和Java虚拟机栈差不多,主要区别就是它是为Native方法服务,而Java虚拟机栈是Java方法服务。

Java堆

对于这个大家应该都很熟悉了,这个一般是虚拟机管理的内存中是最大的一块。这块区域是所有线程共享的,主要是存放对象的实例,几乎所有的对象实例和数组都在这里分配内存,随着JFT的发展,所有对象都分配在堆上也不是那么绝对了。对于开题说到,java不容易出现内存泄漏和内存溢出,因为Java堆有垃圾收集器,所以这里也叫做”GC堆”。现在垃圾收集器基本采用分代收集算法,所以Java堆还可以分为老年代和新生代。

方法区

方法区与GC堆一样,是所有线程共享的,它用来存被虚拟机加载的类信息,常量,静态变量,及时编译器编译后的代码等数据,其实它还有个名称”Non-Heap”(非堆)。目的是与Java堆分开来。在HOtSpot虚拟机上也被叫做永生代,