线程共享?——JVM内存结构

 小伙伴们在面试的时候可能都会碰到这样一个问题

面试官问:“你给我讲一下JVM中线程共享/线程独立区域吧”

 不要慌~~   让我们现在来复习一下这部分的知识🤩~~

 我们先来看一下JVM主要分哪几块区域:

很容易就能理解,线程独占指每一个线程都有自己独立的内存区域,而这一块内存区域可以分为虚拟机栈,本地方法栈和程序计数器,一个进程可以拥有多个线程,而一个进程对应一个JVM实例,故这些线程必然存在共享的内存空间,这块内存空间又可以分为堆和方法区。

目录

一、程序计数器

二、虚拟机栈

三、本地方法栈

终于来到了线程共享区域了!!!🥳🥳

四、堆

如何在Idea中设置堆的大小呢? (仅做了解哈~😛)

五、方法区


让我们先来看看线程独占区域。

一、程序计数器

        我们知道,在一个CPU内核中,线程并不是并行执行的,而是并发执行的,即在一个CPU内核中,CPU会不停的切换线程以执行所有的程序。

        那当CPU再次切换到某个线程时,它是怎么知道当前的线程上次执行到哪了?

这就是程序计数器的作用,程序计数器中保存了下一条执行的指令的地址,这样当CPU再次切换到此线程时,CPU就可以读取程序计数器中保存的下一条要执行的指令的地址,执行下一条指令。也因为其保存的时下一条执行的指令的地址,所以它必须也必然是线程独占的

(毕竟每条线程都有每条线程自己要干的事情🧐)

二、虚拟机栈

        虚拟机栈随着线程的创建而创建。虚拟机栈中保存了此线程拥有的局部变量表(基础数据类型和对象引用地址)和计算过程中产生的中间结果,并参与方法的调用和返回。所以它必然也是线程独占的。

        Java虚拟机栈可以是固定大小,也可以根据计算动态扩展和收缩,我们可以对Java虚拟机栈进行初始值大小的设置,以及最大值的设置。


Java虚拟机栈大小的设置:(了解,不敢兴趣的童鞋可以自行跳过这段🤪🤪~~)

首先我们可以从Oracle官方文档中看到(此为Java 8官方文档,不同JDK可能会有所不同):

很容易就能看出,我们可以使用-Xss size指令或者-XX:ThreadStackSize=size来指定JVM虚拟机栈的大小。

在Idea中,我们可以这样设置JVM虚拟机栈的大小:

 我们可以 根据自己心情 根据业务需求设置大小,如果设置过小(就像上面写的10k),则:

 由此我们也可以看到,在Java 8中,Java虚拟机栈最小大小为108k!🤩🤩🤩

而当我们设置一个正常的数字的时候,例-Xss1024K,我们可以在控制台中看到:

 此时即为设置成功!🥳


当虚拟机栈出现异常时,有两种情况

  1. 当Java虚拟机栈大小固定时,如果程序中的栈分配超过了设置的最大限度,则会出现StackOverflowError异常。
  2. 若Java虚拟机栈时动态扩展的,则当内存不足时,会引发OutOfMemoryError异常(OOM)。

三、本地方法栈

        本地方法栈俗称“C栈”,其与虚拟机栈所发挥的作用是非常相似的。其区别是虚拟机栈为虚拟机执行Java(也就是“字节码”)服务,而本地方法栈则是为虚拟机使用到本地(Native)方法服务。也就是说,本地方法栈中保存了此线程使用本地方法(用非Java语言编写的方法)时拥有的局部变量表(基础数据类型和对象引用地址)和计算过程中产生的中间结果,并参与方法的调用和返回。


终于来到了线程共享区域了!!!🥳🥳

四、堆

        堆是JVM所管理的最大内存区域,程序中所有类实例和数组的内存都存储在此区域。堆在程序开始运行时创建,随着程序的退出而销毁,堆中的数据只要还在使用,就不会被销毁。堆的大小可以是固定的,也可以动态扩展和收缩。我们也可以对堆进行初始大小的控制。

 由官方文档我们可以看出:

1.-Xmn size可以设置堆的初始大小和最大大小

2.-XX:NewSize= 可以设置堆的初始大小

3.-XX:MaxNewSize= 可以设置堆的最大大小

4.-Xms size可以设置堆的最小大小和初始大小(它必须大于等于1M)

5.-Xmx size可以设置堆的最大大小(它必须大于等于2M)

而一旦堆区中的内存大小超过了设置的最大内存大小,则会抛出OutOfMemoryError。


如何在Idea中设置堆的大小呢? (仅做了解哈~😛)

其实和上面设置栈的大小的方式一致


五、方法区

         方法区也是线程共享的,其存储每个类的结构,如运行时常量池,静态变量,字段和方法数据,以及方法和构造函数的代码。

        方法区也是在Java虚拟机启动时而创建的,尽管方法区在逻辑上是堆的一部分,但可以选择不进行垃圾回收或者压缩。方法区可以是固定大小,也可以动态扩展,方法区的内存也不需要连续。我们也可以堆虚拟机的初始大小进行控制,或者在可变大小的方法区中,对其最小内存空间以及最大内存空间进行控制。

        所以当方法区内存超过了设置的最大内存空间是,也会报OutOfMemoryError。

(这里就不对如何控制方法区大小进行介绍了,因为我懒吧🤐)

对于HotSpot虚拟机(是Sun JDK和Open JDK中自带的虚拟机,也是目前使用范围最广的Java虚拟机)来说,不同的JDK方法区的实现是不同的,在JDK 1.7之前,HotSpot技术团队使用的是永久代来实现方法区的(此实现方式更容易造成内存溢出),而在JDK 1.8之后,HotSpot虚拟机开始使用元空间来实现方法区了。

至于永久代为什么会被元空间来替代,大家可以先去看这一篇博客:

永久代为什么会被元空间替代

(后面我有时间我也会写的!!!)😭

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值