Java面试题集-JVM

JVM 部分面试题

JVM是JavaVirtualMachine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。

1、运行时数据区是什么?

虚拟机在执⾏ Java 程序的过程中会把它所管理的内存划分为若⼲不同的数据区,这些区域有各⾃的⽤途、创建和销毁时间。
线程私有:程序计数器、Java 虚拟机栈、本地⽅法栈。
线程共享:Java 堆、⽅法区。
JVM 架构

2、程序计数器是什么?

程序计数器是⼀块较⼩的内存空间,可以看作当前线程所执⾏字节码的⾏号指示器。字节码解释器⼯作时通过改变计数器的值选取下⼀条执⾏指令。分⽀、循环、跳转、线程恢复等功能都需要依赖计数器完成。是唯⼀在虚拟机规范中没有规定内存溢出情况的区域。如果线程正在执⾏ Java ⽅法,计数器记录正在执⾏的虚拟机字节码指令地址。如果是本地⽅法,计数器值为 Undefined。

3、Java虚拟机栈的作用?

Java 虚拟机栈来描述 Java ⽅法的内存模型。每当有新线程创建时就会分配⼀个栈空间,线程结束后栈空间被回收,栈与线程拥有相同的⽣命周期。栈中元素⽤于⽀持虚拟机进⾏⽅法调⽤,每个⽅法在执⾏时都会创建⼀个栈帧存储⽅法的局部变量表、操作栈、动态链接和⽅法出⼝等信息。每个⽅法从调⽤到执⾏完成,就是栈帧从⼊栈到出栈的过程。
有两类异常:① 线程请求的栈深度⼤于虚拟机允许的深度抛出 StackOverflowError。② 如果 JVM 栈容量可以动态扩展,栈扩展⽆法申请⾜够内存抛出 OutOfMemoryError(HotSpot 不可动态扩展,不存在此问题)。

4、本地方法栈的作用?

本地⽅法栈与虚拟机栈作⽤相似,不同的是虚拟机栈为虚拟机执⾏ Java ⽅法服务,本地⽅法栈为虚本地⽅法服务。调⽤本地⽅法时虚拟机栈保持不变,动态链接并直接调⽤指定本地⽅法。
虚拟机规范对本地⽅法栈中⽅法的语⾔与数据结构⽆强制规定,虚拟机可⾃由实现,例如 HotSpot 将虚拟机栈和本地⽅法栈合⼆为⼀。
本地⽅法栈在栈深度异常和栈扩展失败时分别抛出 StackOverflowError 和 OutOfMemoryError。

5、堆的作用是什么?

堆是虚拟机所管理的内存中最⼤的⼀块,被所有线程共享的,在虚拟机启动时创建。堆⽤来存放对象实例,Java ⾥⼏乎所有对象实例都在堆分配内存。堆可以处于物理上不连续的内存空间,逻辑上应该连续,但对于例如数组这样的⼤对象,多数虚拟机实现出于简单、存储⾼效的考虑会要求连续的内存空间。
堆既可以被实现成固定⼤⼩,也可以是可扩展的,可通过 -Xms 和 -Xmx 设置堆的最⼩和最⼤容量,当前主流 JVM 都按照可扩展实现。如果堆没有内存完成实例分配也⽆法扩展,抛出OutOfMemoryError。

6、方法区的作用?

⽅法区⽤于存储被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据。
JDK8 之前使⽤永久代实现⽅法区,容易内存溢出,因为永久代有 -XX:MaxPermSize 上限,即使不设置也有默认⼤⼩。JDK7 把放在永久代的字符串常量池、静态变量等移出,JDK8 中永久代完全废弃,改⽤在本地内存中实现的元空间代替,把 JDK 7 中永久代剩余内容(主要是类型信息)全部移到元空间。
虚拟机规范对⽅法区的约束宽松,除和堆⼀样不需要连续内存和可选择固定⼤⼩/可扩展外,还可以不实现垃圾回收。垃圾回收在⽅法区出现较少,主要⽬标针对常量池和类型卸载。如果⽅法区⽆法满⾜新的内存分配需求,将抛出 OutOfMemoryError。

7、运行时常量池的作用?

运⾏时常量池是⽅法区的⼀部分,Class ⽂件中除了有类的版本、字段、⽅法、接⼝等描述信息外,还有⼀项信息是常量池表,⽤于存放编译器⽣成的各种字⾯量与符号引⽤,这部分内容在类加载后存放到运⾏时常量池。⼀般除了保存 Class ⽂件中描述的符号引⽤外,还会把符号引⽤翻译的直接引⽤也存储在运⾏时常量池。
运⾏时常量池相对于 Class ⽂件常量池的⼀个重要特征是动态性,Java 不要求常量只有编译期才能产⽣,运⾏期间也可以将新的常量放⼊池中,这种特性利⽤较多的是 String 的 intern ⽅法。
运⾏时常量池是⽅法区的⼀部分,受到⽅法区内存的限制,当常量池⽆法再申请到内存时会抛出OutOfMemoryError。

8、直接内存是什么?

直接内存不属于运⾏时数据区,也不是虚拟机规范定义的内存区域,但这部分内存被频繁使⽤,⽽且可能导致内存溢出。
JDK1.4 中新加⼊了 NIO 这种基于通道与缓冲区的 IO,它可以使⽤ Native 函数库直接分配堆外内存,通过⼀个堆⾥的 DirectByteBuffer 对象作为内存的引⽤进⾏操作,避免了在 Java 堆和 Native堆来回复制数据。
直接内存的分配不受 Java 堆⼤⼩的限制,但还是会受到本机总内存及处理器寻址空间限制,⼀般配置虚拟机参数时会根据实际内存设置 -Xmx 等参数信息,但经常忽略直接内存,使内存区域总和⼤于物理内存限制,导致动态扩展时出现 OOM。
由直接内存导致的内存溢出,⼀个明显的特征是在 Heap Dump ⽂件中不会看⻅明显的异常,如果发现内存溢出后产⽣的 Dump ⽂件很⼩,⽽程序中⼜直接或间接使⽤了直接内存(典型的间接使⽤就是NIO),那么就可以考虑检查直接内存⽅⾯的原因。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值