JVM面试题--JVM组成

JVM是什么

Java Virtual Machine  Java程序的运行环境(java二进制字节码的运行环境)

JVM面试题--JVM组成_第1张图片

 运行流程

JVM面试题--JVM组成_第2张图片

什么是程序计数器?

 程序计数器:线程私有的,内部保存的字节码的行号。用于记录正在执行的字节码指令的地址。

我们知道java代码想要运行,需要先把java的源码编译为class字节码文件,在字节码文件当中详细说明了代码的执行过程

JVM面试题--JVM组成_第3张图片

Java 

线程共享的区域:主要用来保存对象实例,数组等,当堆中没有内存空间可分配给实例,也无法再扩展时,则抛出OutOfMemoryError异常。

JVM面试题--JVM组成_第4张图片

在jdk8之后,方法区/永久代被放到了本地内存中,也叫做元空间 

JVM面试题--JVM组成_第5张图片

为什么方法区要放到本地内存呢

因为元空间或者说方法区主要存储的就是一些类或者常量,项目随着动态类加载的情况越来越多,这块内存变得越来越不可控。内存小了,会容易出现内存溢出;大了的话又会浪费内存。所以将方法区要放到本地内存可以防止堆空间内存溢出

总结

JVM面试题--JVM组成_第6张图片

什么是虚拟机栈

JVM面试题--JVM组成_第7张图片

垃圾回收是否涉及栈内存?

垃圾回收主要指就是堆内存,当栈帧弹栈以后,内存就会释放

栈内存分配越大越好吗?

未必,默认的栈内存通常为1024k

栈帧过大会导致线程数变少,例如,机器总内存为512m,目前能活动的线程数则为512个,如果把栈内存改为2048k,那么能活动的栈帧就会减半

方法内的局部变量是否线程安全?

如果方法内局部变量没有逃离方法的作用范围,它是线程安全的

如果是局部变量引用了对象,并逃离方法的作用范围,需要考虑线程安全

JVM面试题--JVM组成_第8张图片

什么时候会出现栈内存溢出?

 JVM面试题--JVM组成_第9张图片

 总结

JVM面试题--JVM组成_第10张图片

堆栈的区别是什么?

栈内存一般会用来存储局部变量和方法调用,但堆内存是用来存储Java对象和数组的的。堆会GC垃圾回收,而栈不会。

栈内存是线程私有的,而堆内存是线程共有的。

两者异常错误不同,但如果栈内存或者堆内存不足都会抛出异常。

     栈空间不足:java.lang.StackOverFlowError

     堆空间不足:java.lang.OutOfMemoryError

能不能解释一下方法区?

方法区(Method Area)是各个线程共享的内存区域(这点和堆一样)

主要存储类的信息、运行时常量池

虚拟机启动的时候创建,关闭虚拟机时释放

如果方法区域中的内存无法满足分配请求,则会抛出OutOfMemoryError: Metaspace

JVM面试题--JVM组成_第11张图片

常量池

JVM面试题--JVM组成_第12张图片

运行时常量池

JVM面试题--JVM组成_第13张图片

 总结

JVM面试题--JVM组成_第14张图片

直接内存

直接内存(操作系统内存):并不属于JVM中的内存结构,不由JVM进行管理。是虚拟机的系统内存,常见于 NIO 操作时,用于数据缓冲区,它分配回收成本较高,但读写性能高

我们平常的io操作就是bio

JVM面试题--JVM组成_第15张图片

常规IO的数据拷贝流程

首先我们知道java并不具备磁盘读写的能力,他必须调用操作系统提供的函数,这里就会调用本地方法(native修饰)来操作磁盘文件

当用户态转变为内核态,这时候就会由cpu的函数区读取磁盘中的文件读取进来,然后会在操作系统中划出一块缓冲区,叫做系统缓冲区。利用缓冲区进行分批次的读取,但是这块缓冲区java代码是没法运行的,这是会在堆中划分一块java缓冲区。

这时候就进行到了下一个阶段,调用输出流的写入操作,进行反复读写,就可以复制到一个目标的位置。但是因为有两块缓冲区,可能会造成不必要的数据的复制,因此效率不高

JVM面试题--JVM组成_第16张图片

JVM面试题--JVM组成_第17张图片

 NIO数据拷贝流程

与上面不同,多了一块直接内存,无论是操作系统还是java代码都可以进行访问

JVM面试题--JVM组成_第18张图片

JVM面试题--JVM组成_第19张图片

 总结

JVM面试题--JVM组成_第20张图片

 

你可能感兴趣的:(jvm)