java面试题-jvm

JVM的由哪些东西组成(What makes up the JVM?)[面试9.0]

在这里插入图片描述

JVM主要组成部分及作用
Java虚拟机底层原理-诸葛[1.5小时]
Java虚拟机调优的目的是什么-诸葛[5分钟]

这里我们讨论的时JDK1.8的情况
JVM包含:
类装载区(Class loader):根据给定的全限定名类名(如:java.lang.Object)来装载class文件到Runtime data area中的method area
执行引擎(Execution engine):执行classes中的指令
本地方法接口(Native Interface):与native libraries交互,是其它编程语言交互的接口
运行时数据区域(Runtime data area):这就是我们常说的JVM的内存

类装载区:
将Java代码转换成字节码,运行时数据区把字节码加载到方法区,由命令解析器执行引擎将字节码翻译成底层系统指令,再交由CPU执行,再调用本地库接口来实现程序的功能

方法区(Method Area):
已被虚拟机加载的类信息,常量,方法,字段和运行时常量池储存在本地内存(元空间(MetaSpace))
静态变量,字符串常量池存放在堆区(Heap Area)

虚拟机栈(Java Virtual Machine Stacks):
每一个线程拥有一块分配的栈内存空间,每个方法执行时会创建一段栈内存空间(栈帧),栈帧主要储存了一下内容
主要存储:
局部变量表: 即局部变量数组主要是方法参数和定义在方法体内的局部变量
操作数栈: 加减乘除运算的临时内存空间
动态链接: 运行时符号引用转为直接引用,保存的地址称为动态链接
方法出口: 方法出口地址表示内嵌方法执行完后执行调用方法之下的代码

本地方法栈(Native Method Stack):
与虚拟机栈的作用是一样的,只不过保存的时Native方法的信息

堆(Java Heap):
Java虚拟机中内存最大的一块,是被所有线程共享的,几乎所有的对象实例都在这里分配内存
存放如:静态变量,String常量池,Class对象等

程序计数器(Program Counter Register):
当前线程所执行的字节码的行号指示器,被阻塞的线程恢复时按这个行号继续执行
分支,循环,跳转,异常处理,线程恢复等基础功能,都需要依赖这个计数器来完成
每一个线程独享一个程序计数器

深拷贝和浅拷贝[面试3.0]

浅拷贝(shallowCopy)只是增加了一个指针指向已存在的内存地址,
深拷贝(deepCopy)是增加了一个指针并且申请了一个新的内存,使这个增加的指针指向这个新的内存,使用深拷贝的情况下,释放内存的时候不会因为出现浅拷贝时释放同一个内存的错误

堆和栈的区别(Difference between heap and stack)[面试3.0]

物理地址
堆的物理地址分配对对象是不连续的,因此性能慢些
栈使用的是数据结构中的栈,先进后出的原则,物理地址分配是连续的,所以性能快

内存分配
堆因为是不连续的,所以分配的内存是在运行期确认的,因此大小不固定,一般堆大小远远大于栈
栈是连续的,所以分配的内存大小要在编译期就确认,大小是固定的

存放的内容
堆存放的是对象的实例和数组,因此该区更关注的是数据的存储(静态的对象存放在堆)
栈存放:局部变量,操作数栈,返回结果,该区更关注的是程序方法的执行(静态变量放在方法区)

程序的可见度
堆对于整个应用程序都是共享,可见
栈只对于线程是可见的,所以也是线程私有,他的生命周期和线程相同

队列和栈是什么?有什么区别?(what are queue and stack? what is the difference between queue and stack?)[面试4.0]

队列和栈都是被用来预存储数据的
可操作的方式不同
队列是在队尾入队,队头出队,两边都可操作,而栈的进栈和出栈都是在栈顶进行的,无法对栈底直接进行操作

操作的方法不同
队列是先进先出(FIFO)即队列的修改是依先进先出的原则进行的,新来的成员总是加入队尾(不能从中间插入),每次离开的成员总是队列头上(不允许中途离队),而栈为后进先出(LIFO),即每次删除(出栈)的总是当前栈中最新的元素,即最后插入(进栈)的元素,而最先插入的被放在栈的底部,要到最后才能删除

JVM怎么创建一个对象的?[面试2.0]

对象创建:new Class,若该Class未被类加载器加载到方法区的话,先加载,若有加载了就开始判断采用两种分配内存的方式:1.指针碰撞(内存规整,创建时只用移动和对象大小相同长度的内存区),2:空闲列表(根据JVM维护的内存可用列表分配一足够大的内存区)
创建中采用CAS自旋或TLAB(本地线程分配缓冲)保证并发安全性

top,jmap,jstat,jstack命令各自有什么用途?[面试5.0]

top系统整体资源使用情况,jmap导出堆到文件,jstat查看jvm运行情况,jstack导出线程堆栈到文件

JVM调优工具有哪些?[面试7.0]

Jstatus,JStack,Jmap,JVisualVM
jstack(查看线程),jmap(查看内存)和jstat(性能分析),JVisualVM(Jdk自带堆栈分析),MAT内存分析

Java虚拟机是如何判定两个Java类是相同的?[面试5.0]

判断类的全名是否相同,判断类的加载器是否相同,两者相同类才相同

JVM参数有哪些分类?[面试5.0]

标准参数: -help, -version -classpath等
X参数: -Xint: 解释执行, -Xcomp: 第一次使用就编译成本地代码, -Xmixed?混合模式
XX参数: 主要用于JVM调优和Debug

如何打印JVM日志?[面试2.0]

-XX:+PrintGC
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-XX:+PrintGCDateStamps

是否有用过JVM内存调优?线上是否遇到过JVM问题?[面试9.0]

STAR面试模型进行阐述:
元空间不够的例子:
背景:现在启动项目报OutOfMemoryError:MetaSpace,分析后得知加载的jar过多,静态变量,类过多导致了该异常
任务:扩大元空间大小MetaSpaceSize,分析加多大
行动:使用jstat看到元空间大小占用96%,然后在JAVA_OPTS中加入设置-XX:MetaspaceSize=256M后解决问题
结果:可以使用jstat检查一下占用情况,适当的加大即可解决问题
JVM堆内存溢出的例子:
背景:页面打转,或加载出来就是空白
任务:检查内存问题,看是否存在堆溢出
行动:+HeapDumpOnOutOfMemoryError和jmap或JVisualVM打印dump文件,利用MAT进行分析
结果:发现查询数据库数据量过大导致堆内存溢出,并且FullGC多次,根据dump定位的OOM代码位置,修改代码解决问题
JVM线程打满的例子:
背景:系统接口调用出现504错误,有连接超时报错
任务:检查是否存在栈线程问题
行动:利用jstat -l进程号,打印进程中的线程栈信息,通过查看线程栈信息,找出进程中是否有Block或者Running的线程
结果:发现连接数过多线程被打满,修改了数据库的连接超时时间问题解决

jstack dump日志文件中重点关注的一些线程状态是那些?[面试5.0]

死锁: Deadlock(重点关注,比如两个服务之间相互占用对方持有的锁就会产生死锁)
等待资源: Waiting on condition(重点关注)
等待获取监视器: Waiting on monitor entry(重点关注)
暂停: Suspended
对象等待中: Object.wait()或TIMED_WAITING
阻塞: Blocked(重点关注)
停止: Parked

什么情况下会出现CPU使用率过高的问题,如何解决此类问题[面试7.0]

程序一直不停的在计算就会出现过高的问题,如循环,可以利用Top查看PID,然后通过jstack导出堆栈信息,采用MAT分析堆栈查找问题出现的代码段来解决

MAT工具内部有哪些东西可以看到?[面试5.0]

Dominator Tree可以看到内存最大的对象,由上往下依次减少,可以右键查看单行选择排除虚引用/弱引用/软引用的GC Root引用链(在导出HeapDump之前要手动出发GC,然后看内存分析,若还存在Strong的引用说明很有可能有内存泄露的情况)
Histogram列出了每个类的实例数量
还可以查看: 引用到该对象的对象,被该对象引用的对象等

JVM逃逸分析有几种类型?[面试5.0]

栈上分配: 默认对象分配在堆中(这种情况说明对象未发生逃逸),但如果一个new出来的对象只会在当前方法上使用,JVM会优化它只在栈上分配,这样做的好处当方法结束后,可立即清理栈上分配的空间(包括整个方法一并清除),避免了堆gc带来的负担
标量替换: 如: o.TEST,其中TEST是对象o内的固定的常量其值为1,那么在使用o.TEST的地方全部直接替换成1
锁消除: 如:synchronized(new Object()),直接删除这个synchronized,因为new Object()已经保证了线程安全
控制台打印GC(-XX:+PrintGC)
开启逃逸分析(-XX:+DoEscapeAnalysis)
开启标量替换(-XX:+EliminateAllocations)
线程本地分配缓存(TLAB,Thread Local Allocation Buffer): 就是给每个线程分配一小块私有的堆空间(是从Eden区划出来的),这样线程在访问堆的共享资源时就不会因为要同步而导致效率降低
逃逸分析-锁消除
逃逸分析-标量替换
逃逸分析-栈上分配

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

2023年Java面试宝典

您的鼓励是对我的肯定,共建希望

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值