JVM内存结构分析

  对于Java程序员来讲,内存是由JVM自动管理的,因此一旦出现内存泄漏或溢出的问题,不了解JVM的内存结构和各个内存区域的工做职责,将对解决问题带来很大的麻烦,本文参照周志明的《深刻理解Java虚拟机》,介绍JVM内存结构,比较枯燥,但对知其然,不知因此然的编码人员来讲仍是有必定帮助的。html

  按照Java虚拟机规范的规定,JVM自动管理的内存将会包括如下几个运行时数据区域。java

 

  JVM内存结构分析

 

  程序计数器程序员

  程序计数器(Program Counter Register)是JVM中一块较小的内存区域,保存着当前线程执行的虚拟机字节码指令的内存地址。Java多线程的实现,实际上是经过线程间的轮流切换并分配处理器执行时间的方式来实现的,在任什么时候刻,处理器都只会执行一个线程中的指令。在多线程场景下,为了保证线程切换回来后,还能恢复到原先状态,找到原先执行的指令,因此每一个线程都会设立一个程序计数器,而且各个线程之间不会互相影响,程序计数器为"线程私有"的内存区域。数据结构

  若是当前线程正在执行Java方法,则程序计数器保存的是虚拟机字节码的内存地址,若是正在执行的是Native方法(非Java方法,JVM底层有许多非Java编写的函数实现),计数器则为空。程序计数器是惟一一个在Java规范中没有规定任何OutOfMemory场景的区域。多线程

  虚拟机栈函数

  虚拟机栈(Java Virtual Machine Stacks)和线程是紧密联系的,每建立一个线程时就会对应建立一个Java栈,因此Java栈也是"线程私有"的内存区域,这个栈中又会对应包含多个栈帧,每调用一个方法时就会往栈中建立并压入一个栈帧,栈帧是用来存储方法数据和部分过程结果的数据结构,每个方法从调用到最终返回结果的过程,就对应一个栈帧从入栈到出栈的过程。编码

  虚拟机栈是一个后入先出的数据结构,线程运行过程当中,只有一个栈帧是处于活跃状态的,被称为"当前活动帧栈",当前活动帧栈始终是虚拟机栈的栈顶元素。线程

 

  JVM内存结构分析

 

  本地方法栈htm

  本地方法栈(Native Method Stack)和虚拟机栈的做用类似,不过虚拟机栈是为Java方法服务的,而本地方法栈是为Native方法服务的。对象

  方法区

  方法区(Method Area)是用于存储类结构信息的地方,包括常量池、静态变量、构造函数等类型信息,类型信息是由类加载器在类加载时从类文件中提取出来的。

  方法区一样存在垃圾收集,由于用户经过自定义加载器加载的一些类一样会成为垃圾,JVM会回收一个未被引用类所占的空间,以使方法区的空间达到最小。

  方法区中还存在着常量池,常量池包含着一些常量和符号引用(加载类的链接阶段中的解析过程会将符号引用转换为直接引用)。

  方法区是线程共享的。

  堆

  堆(heap)是存储java实例或者对象的地方,是GC的主要区域,一样是线程共享的内存区域。

  案例分析一

 

 JVM内存结构分析

 

  案例分析二

 

  JVM内存结构分析

JVM内存结构分析

 

  上面main方法中运行的程序过程以下:

  (1)用户建立了一个Student对象,运行时JVM首先会去方法区寻找该对象的类型信息,没有则使用类加载器classloader将Student.class字节码文件加载至内存中的方法区,并将Student类的类型信息存放至方法区。

  (2)接着JVM在堆中为新的Student实例分配内存空间,这个实例持有着指向方法区的Student类型信息的引用,引用指的是类型信息在方法区中的内存地址。

  (3)在此运行的JVM进程中,会首先起一个线程跑该用户程序,而建立线程的同时也建立了一个虚拟机栈,虚拟机栈用来跟踪线程运行中的一系列方法调用的过程,每调用一个方法就会建立并往栈中压入一个栈帧,栈帧用来存储方法的参数,局部变量和运算过程的临时数据。上面程序中的stu是对Student的引用,就存放于栈中,并持有指向堆中Student实例的内存地址。

  (4)JVM根据stu引用持有的堆中对象的内存地址,定位到堆中的Student实例,因为堆中实例持有指向方法区的Student类型信息的引用,从而得到add()方法的字节码信息,接着执行add()方法包含的指令。

  总结

  一、全部线程共享的内存数据区:方法区,堆。而虚拟机栈,本地方法栈和程序计数器都是线程私有的。

  二、存放于栈中的东西以下:

  2.1每一个线程包含一个栈区,栈中只保存基础数据类型的对象和自定义对象的引用(不是对象)。对象都存放在堆区中。

  2.2每一个栈中的数据(基础数据类型和对象引用)都是私有的,其余栈不能访问。

  2.3方法的形式参数,方法调用完后从栈空间回收

  2.4引用对象的地址,引用完后,栈空间地址当即被回收,堆空间等待GC

  三、存放于堆中的东西以下:

  3.1存储的所有是对象,每一个对象包含一个与之对应的class信息

  3.2 Jvm只有一个堆区(heap)被全部线程共享,堆区中不存放基本类型和对象引用,只存放对象自己

  四、存放于方法区中的东西以下:

  4.1存放线程所执行的字节码指令

  4.2跟堆同样.被全部线程共享.方法区包含:全部的class和static变量

  4.3常量池位于方法区中,见以下图示说明

 

JVM内存结构分析

相关文章
相关标签/搜索