JVM进阶调优系列(2)字节面试:JVM内存区域怎么划分,分别有什么用?

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: 本文详细解析了JVM类加载过程的关键步骤,包括加载验证、准备、解析和初始化等阶段,并介绍了元数据区、程序计数器、虚拟机栈、堆内存及本地方法栈的作用。通过本文,读者可以深入了解JVM的工作原理,理解类加载器的类型及其机制,并掌握类加载过程中各阶段的具体操作。

像字节、阿里、腾讯、美团、京东等大厂面试,JVM调优必问必答必会的问题,重要性不言而喻。


上篇文章详细分析了类加载器类型、双亲委派机制优缺点、以及如何打破双亲委派机制。末尾我们留了一个问题:类加载到内存过程具体会经过那些流程?

1、加载验证:类加载器加载二进制.class文件到内存后,开始验证.class文件是否符合JVM规范,检查格式、语义等是否符合规正确。比如.class文件生成后,被别人直接随便修改编辑,这就会被发现不规范不安全。

2、准备:验证之后,开始给.class的进行分配内存空间(今天重点讲如何分配内存),以及给一个初始默认值。比如加载了这个Demo001ClassLoader类,在准备阶段就需要给Demo001ClassLoader分配内存(放在哪?看完本文就知道),以及要给里面的paramA变量分配内存,并给它赋一个默认0值。

public class Demo001ClassLoader {
    private static int paramA = getParamA();
    private static List<String> strList = new ArrayList<>();
    static {
        strList.add("a");
    }
    public static int getParamA() {
        User user = new User("aa");
        return user.getAge();
    }
}

3、解析:我们代码开发,引用方法、变量,都是通过方法名、变量名去引用。这种是符号引用。在解析阶段,会把符合引用解析成直接引用,这样jvm就可以直接执行 。

4、初始化:这个很重要。在阶段2【准备】,仅仅是给paramA分配空间并赋默认值,初始化就是赋予具体值。这时候初始化,就是开始调用getParamA()方法,发现还有加载User类,然后获取对应值,赋值给paramA变量。以及执行static修饰的代码块。

image.png

一、元数据区MetaSpace

   这个区,主要放类加载器加载进来的.class文件。在JDK8以前,这个也叫方法区。这个元数据区不占用堆内存,这个区是直接使用系统内存。

二、程序计数器(多线程之间独自占有)

    .class文件也是经过编译后的一行行代码指令,每个线程执行代码指令时候,通过程序计数器,记录当前执行字节码指令位置。

三、虚拟机栈(多线程之间独自占有)

   每个线程都有自己的一个虚拟机栈,当访问一个方法时,就给这个方法创建一个栈帧。用来存放方法里的局部变量、方法出口、动态链接等,主要用来存放方法里的局部变量。比如线程执行了ABC 三个方法,A()->B(),B 方法里有个局部变量b->C()。分别创建了ABC栈帧入栈,执行完C方法后,C帧出栈,然后B方法帧的局部变量b出栈,然后B方法帧出栈,最后A方法帧从虚拟机栈出栈。

    以及方法里又调用其他方法,这时候将方法的符号引用,变成直接引用==也叫做动态链接。

四、堆内存-核心的核心(多线程共享读写堆空间数据)

     堆内存就是存放类对象实例,GC回收就是在这个区域进行。在三的虚拟机栈,如果栈里有局部变量,属于八大基本类型数据int、double之类,直接存值,如果是实例对象,局部变量只是存地址引用。局部变量对象的数据就会存在堆内存中。

    在堆内存里,年轻代Young和老年代Old。年轻代分Eden区、S1区、S2区共三个区。默认各自占年轻代的8:1:1空间。

新对象都尝试存放在年轻代的Eden区,如果Eden区放不下,就触发YGC。

五、本地方法栈

    和虚拟机栈有点类似,用来执行native方法,但不是native方法都不是java实现,主要是C++实现。native方法可以直接访问操作系统API、硬件设备,本地方法栈为这些方法的执行提供了环境。

image.png

据此,阅读了系列1和本文,可以轻松回答JVM的类加载器种类作用、双亲委派机制以及其优缺点,还有如何打破双亲委派机制。还有类加载过程做了什么,以及执行main方法后,main线程的虚拟机栈如何对方法栈帧入栈出栈,以及局部变量,.class文件,类变量,实例对象存储,都一清二楚。

今天分享到这,留一个问题,堆对象的生命周期是咋样的呢?什么时候被回收,回收前又如何流转?具体又是被如何回收?

目录
打赏
0
2
3
0
106
分享
相关文章
JVM简介—1.Java内存区域
本文详细介绍了Java虚拟机运行时数据区的各个方面,包括其定义、类型(如程序计数器、Java虚拟机栈、本地方法栈、Java堆、方法区和直接内存)及其作用。文中还探讨了各版本内存区域的变化、直接内存的使用、从线程角度分析Java内存区域、堆与栈的区别、对象创建步骤、对象内存布局及访问定位,并通过实例说明了常见内存溢出问题的原因和表现形式。这些内容帮助开发者深入理解Java内存管理机制,优化应用程序性能并解决潜在的内存问题。
121 29
JVM简介—1.Java内存区域
快速定位并优化CPU 与 JVM 内存性能瓶颈
本文介绍了 Java 应用常见的 CPU & JVM 内存热点原因及优化思路。
676 166
JVM实战—4.JVM垃圾回收器的原理和调优
本文详细探讨了JVM垃圾回收机制,包括新生代ParNew和老年代CMS垃圾回收器的工作原理与优化方法。内容涵盖ParNew的多线程特性、默认线程数设置及适用场景,CMS的四个阶段(初始标记、并发标记、重新标记、并发清理)及其性能分析,以及如何通过合理分配内存区域、调整参数(如-XX:SurvivorRatio、-XX:MaxTenuringThreshold等)来优化垃圾回收。此外,还结合电商大促案例,分析了系统高峰期的内存使用模型,并总结了YGC和FGC的触发条件与优化策略。最后,针对常见问题进行了汇总解答,强调了基于系统运行模型进行JVM参数调优的重要性。
JVM实战—4.JVM垃圾回收器的原理和调优
JVM实战—2.JVM内存设置与对象分配流转
本文详细介绍了JVM内存管理的相关知识,包括:JVM内存划分原理、对象分配与流转、线上系统JVM内存设置、JVM参数优化、问题汇总。
JVM实战—2.JVM内存设置与对象分配流转
JVM简介—2.垃圾回收器和内存分配策略
本文介绍了Java垃圾回收机制的多个方面,包括垃圾回收概述、对象存活判断、引用类型介绍、垃圾收集算法、垃圾收集器设计、具体垃圾回收器详情、Stop The World现象、内存分配与回收策略、新生代配置演示、内存泄漏和溢出问题以及JDK提供的相关工具。
JVM简介—2.垃圾回收器和内存分配策略
如何快速定位并优化CPU 与 JVM 内存性能瓶颈?
如何快速定位并优化CPU 与 JVM 内存性能瓶颈?
|
1月前
|
JVM: 内存、类与垃圾
分代收集算法将内存分为新生代和老年代,分别使用不同的垃圾回收算法。新生代对象使用复制算法,老年代对象使用标记-清除或标记-整理算法。
28 6
JVM实战—5.G1垃圾回收器的原理和调优
本文详细解析了G1垃圾回收器的工作原理及其优化方法。首先介绍了G1通过将堆内存划分为多个Region实现分代回收,有效减少停顿时间,并可通过参数设置控制GC停顿时长。接着分析了G1相较于传统GC的优势,如停顿时间可控、大对象不进入老年代等。还探讨了如何合理设置G1参数以优化性能,包括调整新生代与老年代比例、控制GC频率及避免Full GC。最后结合实际案例说明了G1在大内存场景和对延迟敏感业务中的应用价值,同时解答了关于内存碎片、Region划分对性能影响等问题。
字节面试: es怎么提升性能和精准度?(尼恩独家,史上最全)
本文由40岁老架构师尼恩撰写,针对ES(Elasticsearch)提升搜索性能和精准度的面试题进行详细解析。文章首先指出,提升ES速度和精准度是两个独立的问题,分别涉及性能优化和精准度优化。这些内容不仅有助于应对面试中的难题,还能帮助开发者在实际项目中构建更高效的搜索系统。尼恩强调,掌握这些知识后可以在面试中“吊打”面试官,轻松获得理想Offer。同时,他还提供了《尼恩Java面试宝典PDF》等资源供读者学习参考。
Java JVM 面试题
Java JVM(虚拟机)相关基础面试题