JVM内存模型-备忘录

  生命不息,学习不止!
  JVM内存模型由:堆、栈、方法区、本地方法栈、程序计数器构成了JVM运行时数据区。

JVM内存模型,如下图:


JVM内存模型
Java堆内存(Heap)

  Java堆内存是JVM启动时创建的一块重要的内存区,该区域是所有线程共享的区域。Java堆内存主要的作用就是为所有的对象实例数组分配内存空间,创建的对象实例和数组都被存在Java堆内存中。
  Java堆内存也是JVM GC收集器管理内存区域,在Hotspot虚拟机中堆内存分为两部分新生代老年代,而新生代可划分为eden区survivor区,其中Survivor区又可分为:FromTo两个区域,Java堆内存之所以会这么划分,主要是方便堆对内存的管理。
  Java 堆内存大小可以通过:``-Xms和-Xmx来分配java堆内存的最小和最大内存,可以使用-Xmn来调整年轻代的内存大小。
堆内存结构,如下图:

Java堆内存结构

方法区(Method Area)

  Java方法区是JVM线程共享的一个内存区域,Java方法区主要适用于存放,被JVM加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等信息。
  在JDK8以前方法区的数据都存储在"永久代"中,可以通过-XX:PermSize-XX:MaxPermSize指定JVM中的永久代(方法区)的大小,永久代是在JVM中实现的,并且永久代被占用的内存只有在FullGC的时候有可能被回收,而且回收的表现也一般。正因为这样方法区的内存没有得到很好的管理,在使用的时候,对方法区内存控制不当会出现java.lang.OutOfMemoryError: PermGen space,字符串量池过大、静态变量过多都会导致方法区内存空间不足。例如:我们的业务需要动态通过网络加载类信息,随着时间的延长加载类的信息逐渐变多,方法区内存得不到回收,也会出现OOM。
  到了JDK8,方法区的内存通过元空间替换掉永久代,元空间和永久代没有太多的区别,他们的作用都是方法区的实现。元空间永久代的最大区别就是,元空间不在虚拟机内存中,而是直接使用本地内存来存储方法区数据。
  在默认情况下,元空间的大小仅受本地内存限制,但可以通过:-XX:MetaspaceSize(初始空间大小)和-XX:MaxMetaspaceSize(最大空间)参数来指定元空间的大小,默认是不限制元空间的大小的。元空间还有两个与 GC 相关的参数:

  • -XX:MinMetaspaceFreeRatio:在GC之后,最小的元空间剩余空间容量的百分比
  • -XX:MaxMetaspaceFreeRatio:在GC之后,最大的元空间剩余空间容量的百分比
JVM栈(Java Virtual Machine Stacks)

   JVM栈是JVM线程私有的内存区域,栈的生命会周期和Java线程一样。JVM栈描述的是Java方法执行的线程模型。每一个java方法被执行的时候,JVM都会同步创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等。
   每一个Java方法在被调用一直到执行结束的过程,都会对应着一个栈帧在JVM栈中的入栈出栈的过程。
  局部变量表存放了编译时期可知的JVM基本数据类型(boolean、byte、char、short、int、 float、long、double)、对象引用 和 returnAddress 类型。
  这些数据类型在局部变量表中的存储空间以局部变量槽(Slot)来表示,其中64位长度的longdouble类型的数据会占用两个变量槽,其余的数据类型只占用一个。
  局部变量表所需的内存空间在编译期间完成分配,当进入一个方法时,这个方法需要在栈帧中分配多大的局部变量空间是完全确定的,方法运行期间不会改变局部变量表的大小
java虚拟机栈结构:

java虚拟机栈

程序计数器(Program Counter Register)

  程序计数器是JVM线程私有的,是一块内存较小的空间。可以把程序计数器看作是当前线程执行字节码行号的指示器
  字节码解释器在工作的时候就是通过改变程序计数器的值来选取下一条要执行的字节码指令。
  Java虚拟机的多线程是通过线程轮流切换、分配处理器执行时间的方式来实现的,在任何一 个确定的时刻,一个处理器都只会执行一条线程中的指令。因此,为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,各条线程之间计数器互不影响,独立存储。

本地方法栈(Native M ethod Stacks)

  本地方法栈JVM栈非常相似,其区别是JVM栈为虚拟机执行Java方法服务,而本地方法栈则是为虚拟机使用到的本地方法服务.

运行时常量池(Runtime Constant Pool)

  运行时常量池是方法区的一部分。Class文件中除了有类的版本、字 段、方法、接口等描述信息外,还有一项信息是常量池表(Constant Pool Table),用于存放编译期生成的各种字面量与符号引用,这部分内容将在类加载后存放到方法区的运行时常量池中。

  致此,JVM内存结构介绍结束!
  生命不息,学习不止!

你可能感兴趣的:(JVM内存模型-备忘录)