一、引言
在提到Java语言与C++语言的不同时,往往第一反应就是Java的垃圾回收技术。简单地来说,在Java的代码中,如果我们new了一个对象,是不需要考虑在使用完成后对该对象进行析构的。因为Java虚拟机的内存动态管理技术,会帮我们智能的管理程序的内存。看似好像一切很完美,但是问题来了,既然Java会智能的帮我们管理内存,为什么还是会遇到内存溢出的异常?内存泄露又是怎么回事儿呢?为了解开这些问题,我们就要首先了解一下在程序的运行过程中,Java虚拟机管理了哪些内存区域。
二、Java虚拟机
在探讨Java虚拟机管理了哪些内存区域前,我想首先来描述下Java虚拟机。
Java虚拟机(Java Virtual Machine,简称JVM),它是运行Java程序必不可少的环境。当编写完Java语言的程序后,经过编译就得到了可以直接在JVM上运行的字节码bytecode,该字节码可以运行在安装了JVM的任何平台上(Windows,Linux,Mac等),实现了Java程序的跨平台运行。
既然JVM能够用来解释运行Java程序的字节码,那么它具有怎样的内部结构呢?JVM更像是一个小型的处理系统,它具有一套字节码指令集(用于解释字节码),一组寄存器,和其所管理的内存区域(即Java程序运行所需的JVM运行时数据区)。其中JVM运行时数据区就是JVM动态管理内存的区域,也是我们下面所要介绍的。
为自己澄清一个概念:
JVM内部是没有进程的概念的,它只有线程。每一个Java程序的运行,都是需要一个新的JVM的。所以,每一个运行的JVM是一个进程,而其内部运行着一个Java程序的各个线程。 考虑java程序运行时的命令:
java HelloWorld
其中java就是用来启动JVM,然后来装载类HelloWorld的。多个程序就需要多个JVM。
三、JVM运行时数据区
在Java程序运行时,需要对类进行加载,对代码进行加载,对常量、静态变量存储,对动态生成的对象进行管理等,因此不会将这些数据都杂乱的存放在一块数据区里,JVM对运行时数据区进行了如下的划分:
1. 线程隔离的数据区
- (1) 程序计数器
- (2) 虚拟机栈
- (3) 本地方法栈
2. 线程共享的数据区
- (1) 方法区
- (2) 堆