剑指Offer(JVM)——Java内存模型


首先来简单介绍一下内存:
在这里插入图片描述
程序执行过程中需不断的将逻辑地址和物理地址进行映射从而找到指令具体执行的位置。

Java程序运行在虚拟机上,运行时候需要内存空间,执行Java程序过程中JVM内部将整个JVM划分成不同的数据区域去管理。

C语言的编译器在划分区域时候将管理的区域划分成数据段和代码段。数据段分为堆、栈和方法区,Java中内存区域是如何划分的可以从线程角度和模型角度去分析一下:

线程角度

哪些是线程私有的区域哪些是线程共享的区域:
在这里插入图片描述

1、程序计数器(Program Counter Register)

程序计数器在Java内存中占据一段较小的内存模型。

  • 当前线程所执行的字节码的行号指示器(逻辑)而非物理指示器;
  • 改变计数器的值来选取下一条需要执行的字节码指令;
  • 和线程是一对一的关系即"线程私有",因为多线程需要通过轮换分配CPU资源去进行高效执行;
  • 对Java方法计数,如果是Native方法计数器值为Undefined;
  • 最重要的是不会发生内存泄露(因为记录的仅仅是行号)。

程序计数器本质上是逻辑计数器不是物理计数器,为了保证程序切换线程之后都能回到正确的位置每个线程都有一个独立的程序计数器,并且只为Java方法计数

2、Java虚拟机栈(Stack)

虚拟机栈也是线程私有的,是Java方法执行的内存模型,每个方法被执行时候都会产生一个栈帧用来存储方法,方法开始执行时候入栈方法执行完毕后出栈
在这里插入图片描述
栈帧中存储着局部变量表、操作栈、动态连接、返回地址等等其他信息,局部变量表和操作数栈是有一定的区别的,简单来介绍一下两者:

局部变量表:包含方法执行过程中的所有变量;
操作数栈:入栈、出栈、复制、交换、产生消费变量。

举一个简单的例子做为解释参考:
在这里插入图片描述
那么为什么在递归的时候会引发java.lang.StackOverflowError异常,实现一个简单的例子:
在这里插入图片描述
那么为什么在递归的时候会引发java.lang.StackOverflowError异常呢???

线程执行一个方法时候会创建一个对应的栈帧并将其压入虚拟机栈中,方法执行完毕后将栈帧出栈。在每次递归的时候会调用一个方法生成一个栈帧,递归没结束方法还保存在虚拟机栈上超过了一定的限度就会导致栈帧溢出最后引发java.lang.StackOverflowError异常。

虚拟机栈过多还会引起OOM异常:

执行递归程序当虚拟机栈容量快用完时会去动态申请新的内存空间,如果没有新的内存空间的话就会造成OOM。

举个简单的例子:
在这里插入图片描述
常规来说该程序会报:java.land.OutOfMemoryError:unable to create new native thread
在这里不建议执行这个程序因为Windows平台虚拟机Java线程映射到操作系统的内核线程上执行这个程序可能会死机。

这个时候系统处于假死状态。

3、本地方法栈(Native Stack)

和虚拟机栈相似,主要作用是标注了native方法。

4、元空间(MetaSpace)和永久代(PermGen)区别

JDK8开始将类的元数据放在本地内存中这个部分叫做MetaSpace元空间。这个区域在JDK7之前属于永久代,元空间和永久代都是存储class的相关信息包括class对象的Method,实际上元空间和永久代都是之前说的方法区的实现只是在实现上有些不同,因此说方法区只是一种JVM的规范,JDK8及之后版本中字符串常量池已经被移动到了Java堆中,使用元空间替换掉永久代

元空间和永久代最大区别在于:元空间使用本地内存,永久代使用的是JVM内存,使用本地内存最大的好处就是在JDK8及之后的版本中不会出现oom:PermGen space这个异常因为内存只会受到本地内存大小的限制。

JVM不会无限的使用本地内存是动态进行设置的。

MetaSpace比PermGen优势在于:

  1. 字符串常量存在永久代中,容易出现性能问题和内存溢出;
  2. 类和方法信息难以确定,给永久代的大小指定带来困难;
  3. 永久代会为GC带来不必要的复杂性,并且回收率很低;
  4. 元空间可以更加方便的将HotSpot与其他JVM如Jrockit集成。

5、堆(Heap)

Java堆是Java内存管理中最大的一个区域,是所有内存共享的一块区域,其中一个非常关键的作用就是存放类的实例所有的对象实例都在堆里面分配内存。
在这里插入图片描述
如果堆没有足够的内存分配给对象实例就会抛出oom异常。

堆也是GC管理的主要区域,也可称为GC堆。Java堆采用了分代垃圾回收算法,分成了新生代(Eden)和老年代(tenured)。

在这里插入图片描述

发布了242 篇原创文章 · 获赞 23 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_44240370/article/details/104062306