引言
最近准备看两本书,一本是《深入理解计算机系统》,另一本是《深入理解Java虚拟机》,两本都是提升内功的必备经书,思来想去,最终还是决定先看jvm(因为这本书相对薄一些)。现在,让我们一起来探索下jvm的奥秘吧,如若有不同理解的地方,欢迎各位猿友一起探讨。
运行时数据区域
Java虚拟机在执行Java程序的过程中会把它管理的内存划分为5个不同的数据区域。分别是:程序计数器、Java虚拟机栈、本地方法栈、Java堆、元数据区(方法区)。
结构图(基于JDK8)
内存区域详解
程序计数器(线程独有):它是一块较小的内存空间,可以看作是当前线程所执行的字节码行号指示器,记载着每一个线程当前运行Java方法的地址,如果正在执行的是Native方法,则这个计数器值为空。程序中,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖程序计数器来完成。直观想象下,在多线程中,线程切换后,如果没有记住每个线程当前的位置,那么如何能恢复呢。因此,每个线程都有一个独立的程序计数器。
Java虚拟机栈(线程独有):Java虚拟机栈在线程创建的同时创建,用于储存栈帧,它是线程私有的,生命周期与线程相同。注:栈帧是随着方法的创建而创建,随着方法的结束而结束,它存储了方法的局部变量表、操作数栈、动态连接和方法返回地址等信息,简单来说,就是方法运行时的临时数据存储区域。
本地方法栈(线程独有):本地方法栈用来支持Native方法(由 C 语言实现)执行。
Java堆(全局共享):Java堆随着虚拟机的启动而创建,几乎所有的实例对象和数组都要在这里分配内存,是虚拟机内存中最大的一块。
元数据区(全局共享):元数据区是对 JVM 规范中方法区的实现,方法区用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。JDK 1.8 同 JDK 1.7 比,最大的差别就是:元数据区取代了永久代,且元数据空间并不在虚拟机中,而是使用本地内存。
内存管理
内存的管理分为内存的分配和内存的释放,上面的五个内存区域,大致可以分为两类:全局共享和线程独有。
线程独有的这部分内存可以理解为随着线程的启动而创建,随着线程的销毁而释放,这部分内存由Java虚拟机来主动管理,不需要垃圾收集器(GC)的管理。
全局共享的这部分内存的分配主要由程序中显示的new关键字来触发的,至于在哪分配,如何分配则是由Java虚拟机来决定的。而这部分内存的释放,则是由垃圾收集器(GC)来管理的。
结束语
本章节的内容到此结束,下一章将介绍GC的策略及算法。