本文作者:李敏,叩丁狼高级讲师。原创文章,转载请注明出处。
前言
为什么要了解虚拟机如何操作内存?
java与c/c++之间有一堵由内存动态分配和垃圾收集技术所围成的"高墙",墙外面的人想进去,墙里面的人却想出来.
对于java程序员来说,在虚拟机自动内存管理机制的帮助下,不再需要为每一个new操作去写配对的delete/free代码,不容易出现内存泄漏和内存溢出.有虚拟机管理内存,这一切看起来都很美好.但是,也正因为java程序员把内存控制的权力给了java虚拟机,一旦出现内存泄漏和溢出方面的问题,如果不了解虚拟机是怎么样使用内存的,那么排查错误将会成为一项异常艰难的工作.
3.1 虚拟机内存模型
java虚拟机在执行java程序的过程中,会把所有它管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途,.根据的规定,java虚拟机所管理的内存将会包括以下几个运行时数据区域:
1. 程序计数器
2. java虚拟机栈
3. 本地方法栈
4. java堆
5. 方法区
6. 运行时常量池
7. 直接内存
3.1.1 程序计数器
Program Counter Register
内存空间小,线程私有.它可以看做是当前线程所执行的字节码的行号指示器.也就是说,线程主要是执行任务,而执行到哪里,需要使用程序计数器来记录.字节码解释器工作是就是通过改变这个计数器的值来选取下一条需要执行指令的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖计数器完成.
由于java虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的,所以,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间计数器互不影响,独立存储,所以我们说,它是线程私有的.
如果线程正在执行一个 Java 方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是 Native 方法,这个计数器的值则为 (Undefined)。此内存区域是唯一一个在 Java 虚拟机规范中没有规定任何 OutOfMemoryError 情况的区域。
3.1.2 虚拟机栈
java virtual Machine Stacks
线程私有,生命周期和线程一致。描述的是 Java 方法执行的内存模型:每个方法在执行时都会创建一个栈帧(S