字节二面:JVM各区域间是如何协同工作的?

#每天一道面试题# 56

JVM可以分为运行时数据区以及类加载器、执行引擎、本地方法库

运行时数据区包含以下部分:

1.方法区:非堆

2.虚拟机栈:本地方法

3.本地方法栈:native方法

4.堆:新生代(from、to、eden)、老年代

5.程序计数器:标记当前线程所执行的位置,方便上下文切换完成以后继续执行

非运行时数据区:

6.类加载器:启动类加载器、扩展类加载器、系统类加载器、自定义类加载器;

7.执行引擎:将字节码指令解释/编译为对应平台上的本地机器指令;

8.本地方法库:Java调用跨语言(C、C++)的接口。

问题一:堆、栈、方法区之间数据存储怎么协调的?

答:栈指向方法区;栈指向堆、堆指向方法区、方法区指向堆;

栈:栈帧(局部变量表、操作数栈、返回地址、动态链接)

栈 -> 方法区

​ 动态链接指向 Klass 对象在方法区的地址

栈 -> 堆

​ 局部变量表存放的引用变量,指向真实对象存放在堆中的地址

方法区 -> 堆(JDK8以后方法区不在指向堆)

​ JDK7 以前静态属性在方法区中;

​ JDK8 及以后,存在堆中元数据类Class中;

堆 -> 方法区

​ klass pointer 作用去找到对象依赖的类;

问题二:双亲委派机制了解吗?

答:双亲委派:沙箱安全机制,防止核心API库被随意篡改。

还有一些场景破坏了双亲委派机制,因为受类加载器受到加载范围的限制,存在某些情况下父类加载器无法加载到需要的文件。在JDBC、Tomcat、OSGI 场景就需要委托子类加载器去加载class文件破坏了双亲委派机制。

问题三:内存分配策略了解吗?

答:空闲列表:idle(空闲),used(已用),available(可用);

指针碰撞:自旋 + CAS;

问题四:为什么要引入元空间?

1.永久代缺点

​ 存在内存瓶颈

​ GC:字符串常量池,动态字节码

​ 存储类信息

2.元空间能解决永久代问题,它本身还存在问题吗?

​ 元空间存储应用程序的类加载器信息,当前实现回收以后会产生内存碎片

问题五:方法区,元空间,永久代之间关系?

方法区是JVM的规范;元空间与永久代是规范落地实现,7叫永久代在JVM内部,8及以后叫元空间使用直接内存; 容易混淆的概念:

堆空间不是全部被线程共享的,TLAB:线程私有的堆空间

对象不一定存放在堆中,方法内局部变量,存在栈中

元空间不等于方法区,方法区抛开元空间以外还包括CodeCache存储JIT的代码等。