【对线面试】JVM全网最强面试对答

文章目录

面试官: 今天我们来聊聊JVM吧!!!

:好的,我准备好了。

面试官:来,给你张草稿纸,需要方便你画图和写伪码。

:谢谢!

面试官:那你先说一下 JVM 的内存区域有哪些?

:好的。

我: 根据 《Java 虚拟机规范》的规定,Java 虚拟机锁管理的内存将会包括程序计数器、虚拟机栈、本地方法栈、堆、方法区这几个运行时区域

在这里插入图片描述

:我挨个讲一下这些内存区域的用途吧!

:首先是程序计数器,是一块相对较小的空间,它相当于一个执行程序的行号指示器。它记录程序下一条需要执行的指令的地址,分支、循环、跳转、异常处理、线程恢复等基础功能并且是线程私有的。

:Java 虚拟机栈,我们在写程序的时候都会为了复用封装很多个方法,每个方法在执行的同时都会创建一个栈帧用于存储局部变量表、操作数栈、动态链接、方法出口等这些在执行函数时会用到的信息信息。和程序计数器一样,这块内存也是线程私有的。

:本地方法栈,它与虚拟机栈的作用非常的像,它们的区别就是虚拟机栈是为执行 Java 方法服务的,而本地方法栈是为 native 服务的,它也是线程私有的

:Java堆,在日常的代码里面处处都有创建对象的代码,堆就是存放这些对象的内存区域,可想而知这块区域也是最大的一块区域,而且它是被所有线程共享的区域

:最后一个方法区,他和Java堆一样是在各个线程中共享的内存区域,它是用来存储已经被虚拟机加载的类信息、常量、静态变量以及即时编译后的代码,在 HotSpot 虚拟机上 虚拟机的设计人员用永久代来实现方法区。

面试官:很好,你刚刚提到永久代,那你知道永久代和元空间的区别吗

:嗯嗯,知道的

:我们刚刚讲的方法区这块运行内存它是在《Java 虚拟机规范》里面定义的。不同的虚拟机对这个方法区的定义有不同的实现,在HotSpot虚拟机中在 JDK1.7 版本之前的方法区的实现叫永久代,JDK1.8 之后的实现叫元空间

:至于它们两个的区别嘛,最大的区别在于元空间并不在虚拟机中,而是在本地内存。

:除此之外它们参数调配也改变了,JDK1.7 通过-xx:Permsize来设置永久代初始分配空间和-XX:MaxPermsize来设定永久代最大可分配空间,而元空间大小可以使用参数 -XX:MetaspaceSize 和 -XX:MaxMetaspaceSize指定。

面试官:很不错,那我再问问,那你知道为什么 Java8 之后要移除永久代替换成元空间吗?

:这个嘛!

按照官方上的说法是为了 JRockit 和 Hotspot 融合工作,JRockit不需要配置永久代,因为JRockit没有永久代

:而且程序员很难确定永久代的空间大小,某些业务场景下不断的做类加载等工作会导致永久代空间不足,但是元空间使用本地内存,默认情况下本地大小限制的。

:还有一点就是调优困难,方法区的垃圾收集主要回收两部分内容:常量池中废弃的常量和不再使用的类型。一般来说这个区域的回收效果比较难令人满意但是这部分区域的回收有时又确实是必要的。以前sun公司的Bug列表中,曾出现过的若干个严重的Bug就是由于低版本的HotSpot虚拟机对此区域未完全回收而导致内存泄漏。

面试官:JMM 是什么能简单说一下么?

JMM (Java Memory Model)是Java内存模型,JMM定义了程序中各个共享变量的访问规则,即在虚拟机中将变量存储到内存和从内存读取变量这样的底层细节

我:我来给您画一画这个图:
在这里插入图片描述

:每条线程还有自己的工作内存,线程的工作内存保存了主内存的副本拷贝,对变量的操作在工作内存中进行,不能直接操作主内存中的变量.不同线程间无法直接访问对方的工作内存变量,需要通过主内存完成

面试官:那你能聊聊主内存和工作内存是如何交互操作的吗?

:可以的!

:Java 内存模型定义了以下8种操作来完成,它们都是原子操作(除了对 long 和double 类型的变量)

lock(锁定),作用于主内存中的变量,它将一个变量标志为一个线程独占的状态。

unlock(解锁),作用于主内存中的变量,解除变量的锁定状态,被解除锁定状态的变量才能被其他线程锁定。

read(读取),作用于主内存中的变量,它把一个变量的值从主内存中传递到工作内存,以便进行下一步的load操作。

load(载入),作用于工作内存中的变量,它把read操作传递来的变量值放到工作内存中的变量副本中。

use(使用),作用于工作内存中的变量,这个操作把变量副本中的值传递给执行引擎。当执行需要使用到变量值的字节码指令的时候就会执行这个操作。

assign(赋值),作用于工作内存中的变量,接收执行引擎传递过来的值,将其赋给工作内存中的变量。当执行赋值的字节码指令的时候就会执行这个操作。

store(存储),作用于工作内存中的变量,它把工作内存中的值传递到主内存中来,以便进行下一步write操作。

write(写入),作用于主内存中的变量,它把store传递过来的值放到主内存的变量中。

这里给您画一下具体的交互流程图:

在这里插入图片描述

面试官:可以的,我们接着来聊。

面试官:我们聊聊堆这块内存,你刚刚提到了对象是分配在堆内存里的,那怎么判断是否要回收呢?

:主流的商用程序都是用可达性分析算法来判定对象是否存活,还有一种引用计数的方法也可以判断,不过有些缺陷

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值