JVM调优面试题——基础知识

news2025/4/9 19:51:16

文章目录

  • 1、JDK,JRE以及JVM的关系
  • 2、编译器到底干了什么事?
  • 3、类加载机制是什么?
    • 3.1、装载(Load)
    • 3.2、链接(Link)
    • 3.3、初始化(Initialize)
  • 4、类加载器有哪些?
  • 5、什么是双亲委派机制?
  • 6、介绍一下JVM内存划分(运行时数据区)
    • 6.1、方法区
    • 6.2、Heap(堆)
    • 6.3、Java Virtual Machine Stacks(虚拟机栈)
  • 7、堆为什么进行分代设计?
  • 8、老年代的担保机制
  • 9、为什么Eden:S0:S1 是8:1:1
  • 10、对象的创建以及分配过程
  • 11、方法区、元数据区、持久代是什么关系?
  • 12、对象在内存中的布局

1、JDK,JRE以及JVM的关系

JDK全称为Java Development Kit,是Java开发人员在编写Java程序时使用的开发工具包。如图所示,其包括了JRE和JVM。
其中JRE是Java程序的运行环境,提供了JVM的实现和一些基本类库。
而JVM则是识别.class文件中的指令并调用操作系统完成指令动作。
03.png

2、编译器到底干了什么事?

仅仅是将我们的 .java 文件转换成了 .class 文件,实际上就是文件格式的转换。

image.png

3、类加载机制是什么?

所谓类加载机制就是:虚拟机把Class文件加载到内存,并对数据进行校验、转换解析和初始化等操作,形成虚拟机可以直接使用的Java类型,即java.lang.Class 。具体为以下几个步骤:

image.png

3.1、装载(Load)

装载的操作其实就是查找和导入class文件

  1. 通过一个类的全限定名获取定义此类的二进制字节流(全限定名是将类名中的.替换为/,例如 java/lang.String)
  2. 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
  3. 在Java堆中生成一个代表这个类的java.lang.Class对象,作为对方法区中这些数据的访问入口

3.2、链接(Link)

  • 验证(Verify):保证被加载类的正确性
  1. 文件格式验证
  2. 元数据验证
  3. 字节码验证
  4. 符号引用验证
  • 准备(Prepare):为类的静态变量分配内存,并将其初始化为默认值

    public class Demo1 {
    private static int i;
    
    public static void main(String[] args) {
        // 正常打印出0,因为静态变量i在准备阶段会有默认值0
        System.out.println(i);
    }
    }
    
    public class Demo2 {
        public static void main(String[] args) {
            // 编译通不过,因为局部变量没有赋值不能被使用
            int i;
            System.out.println(i);
        }
    }
    
  • 解析(Resolve):把类中的符号引用转换为直接引用的过程
    主要针对类或接口、字段、类方法、接口方法、方法类型、方法句柄和调用限定符7类符号引用进行。

符号引用就是一组符号来描述目标
直接引用就是直接指向目标的指针、相对偏移量或一个间接定位到目标的句柄

3.3、初始化(Initialize)

对类的静态变量,静态代码块执行初始化操作

4、类加载器有哪些?

在装载(Load)阶段,其中第(1)步:通过一个类的全限定名获取定义此类的二进制字节流,需要借助类装载器完成,顾名思义,就是用来装载Class文件的。

  1. Bootstrap ClassLoader 负责加载 JAVA_HOME中 jre/lib/rt.jar 里所有的class或Xbootclassoath选项指定的jar包。由C++实现,不是ClassLoader子类。
  2. Extension ClassLoader 负责加载java平台中扩展功能的一些jar包,包括`$$JAVA_HOME中jre/lib/*.jar 或 -Djava.ext.dirs指定目录下的jar包。
  3. App ClassLoader 负责加载classpath中指定的jar包及Djava.class.path所指定目录下的类和jar包。
  4. Custom ClassLoader 通过java.lang.ClassLoader的子类自定义加载class,属于应用程序根据自身需要自定义的ClassLoader,如tomcat、jboss都会根据j2ee规范自行实现ClassLoader。

image.png

5、什么是双亲委派机制?

双亲委派是指在加载类的时候,如上图,按照类加载器的顺序向上检查该类是否加载过,向下委派是否可以加载该类。 避免类重复加载并且保证安全性。其执行过程如下图

image.png

类加载源码

protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has already been loaded
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    if (parent != null) {
                        c = parent.loadClass(name, false);
                    } else {
                        c = findBootstrapClassOrNull(name);
                    }
                } catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }

                if (c == null) {
                    // If still not found, then invoke findClass in order
                    // to find the class.
                    long t1 = System.nanoTime();
                    c = findClass(name);

                    // this is the defining class loader; record the stats
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }

6、介绍一下JVM内存划分(运行时数据区)

image.png

6.1、方法区

方法区是各个线程共享的内存区域,在虚拟机启动时创建。虽然Java虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却又一个别名叫做Non-Heap(非堆),目的是与Java堆区分开来
用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据
当方法区无法满足内存分配需求时,将抛出OutOfMemoryError异常

注意:JVM运行时数据区是一种规范,在JDK 8中的实现就是Metaspace,在JDK6或7中的实现就是Perm Space

6.2、Heap(堆)

Java堆是Java虚拟机所管理内存中最大的一块,在虚拟机启动时创建,被所有线程共享。
Java对象实例以及数组都在堆上分配。

6.3、Java Virtual Machine Stacks(虚拟机栈)

虚拟机栈是一个线程执行的区域,保存着一个线程中方法的调用状态。所以虚拟机栈是线程私有的,随着线程的创建而创建。
每一个被线程执行的方法,为该栈中的栈帧,即每个方法对应一个栈帧。(调用一个方法,就会向栈中压入一个栈帧;一个方法调用完成,就会把该栈帧从栈中弹出。)
每个栈帧中包括局部变量表(Local Variables)、操作数栈(Operand Stack)、动态链接、方法返回地址和附加信息。

  • 局部变量表:方法中定义的局部变量以及方法的参数存放在这张表中。如需要使用的话,必须通过相关指令将其加载至操作数栈中作为操作数使用。
  • 操作数栈:以压栈和出栈的方式存储操作数的
  • 动态链接:符号引用转换为直接引用

image.png

7、堆为什么进行分代设计?

如下图,堆被分为Young区、Old区,其中Young区又分为Eden区、Survivor区,而Survivor区又分为S0和S1。

image.png
为什么这样设计有以下原因:

  1. 如果堆没有分代,等到堆空间满了进行清理时,需要消耗很长的时间去清理,期间应用也无法运行。
  2. 因为大多数对象生存时间是很短的(大多对象都是执行完方法后就没用了),需要及时被清理,但是又不能清理整个堆,所以划分了Young区、Old区,这样对象生存时间短的放到Young区,生存时间长的放到Old区,每次只清理Young区,提高效率。
  3. 此时如果来了一个新对象,并且Young区空间足以装下新的对象,但是因为Young区反复被清理过几次,内存空间不连续,没有完整的空间装下新对象,就会造成空间浪费。在这里插入图片描述
  4. 这个时候如果有另外一个区域可以存放Young区的4个存活对象时(此时放入Old区只会加快清理的次数),新对象就可以正常放进来,所以有了Eden区、Survivor区。
  5. 但是只有一个Survivor区也会存在内存碎片问题,所以Survivor区分为S0和S1,当Young GC时,将Eden区和其中一个S区的对象都迁移到另一个S区,从而解决内存碎片的问题。
    在这里插入图片描述

8、老年代的担保机制

当有一个新的对象Young区无法分配空间时,直接放到老年代。

9、为什么Eden:S0:S1 是8:1:1

  1. 大多数对象生存时间是很短的,并且在Eden就可能会被清理掉
  2. S0和S1需要来回存放对方以及Eden区的对象,所以比例需要一致

10、对象的创建以及分配过程

23.png

11、方法区、元数据区、持久代是什么关系?

方法区可以看作是一个规范,JDK1.7之前的实现是持久代,JDK1.8以及其之后的实现是元数据区。

元数据区的优势是,如果本机内存为16G尽管只给JVM分配了4G,元数据区也是会用到本机的其他12G内存,这样的好处是我们不用估算类信息、常量、静态变量这些数据的占用空间。

如下图,方法区中的静态变量、常量在运行时内存中,而类信息在直接内存中。
image.png

12、对象在内存中的布局

image.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/385312.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[蓝桥杯] 数学与简单DP问题

文章目录 一、简单数学问题习题练习 1、1 买不到的数目 1、1、1 题目描述 1、1、2 题解关键思路与解答 1、2 饮料换购 1、2、1 题目描述 1、2、2 题解关键思路与解答 二、DP问题习题练习 2、1 背包问题 2、1、1 题目描述 2、1、2 题解关键思路与解答 2、2 摘花生 2、2、1 题目…

收个滴滴Offer:从小伙三面经历,看看需要学点啥?

说在前面 在尼恩的&#xff08;50&#xff09;读者社群中&#xff0c;经常有小伙伴&#xff0c;需要面试大厂。 后续结合一些大厂的面试真题&#xff0c;给大家梳理一下学习路径&#xff0c;看看大家需要学点啥&#xff1f; 这里也一并把题目以及参考答案&#xff0c;收入咱…

Spring 容器创建初始化,获取bean流程分析

Spring 容器创建初始化&#xff0c;获取bean流程分析 Spring 容器创建初始化 流程分析 1、首先读取bean.xml 文件 2、扫描指定的包 com.hspedu.spring.component 2.1、扫描包&#xff0c;得到bean的class对象&#xff0c;排除包下不是bean的 2.2、扫描将bean信息封装BeanDef…

python之selenium库安装及用法(定位法、获取文本、文本框输入、鼠标点击、滑动滚动条)

一、selenium库安装 pip install selenium二、浏览器驱动安装 谷歌浏览器驱动下载地址&#xff1a;https://chromedriver.storage.googleapis.com/index.html 根据你电脑的谷歌浏览器版本&#xff0c;下载相应的就行。我下载的是110.0.5481.XX中的chromedriver_win32.zip 下载…

无公网IP快解析实现U+随时随地访问

现阶段商品从生产到消费者手中要经过多个环节&#xff0c;为实现对每一个环节进行管理&#xff0c;越来越多的企业选择通过信息化手段来实现。供应链管理系统配合供应链中各实体的业务需求&#xff0c;使操作流程和信息系统紧密配合&#xff0c;做到各环节无缝链接&#xff0c;…

【C++】string类的使用

目录 一、标准库中的string类 二、string类的常用接口 1、string类对象的常见构造 2、string类对象的容量操作 2.1、size 与 length 2.2、capacity 与 reserve 2.3、resize 2.4、总结 3、string类对象的访问及遍历操作 3.1、operator[] 与 at 3.2、begin end 3.3、…

Portraiture5人像磨皮润色修饰插件

Portraiture3和Portraiture4这两个版本大家用的比较多&#xff0c;那是因为这两个版本是中文比较全的版本。portraiture是一款强大的64位PS磨皮滤镜&#xff0c;利用该PS滤镜插件可以对图片中的人物进行润色&#xff0c;磨皮等操作&#xff0c;处理皮肤材质、头发等。帮您消除了…

HNU工训中心:平台 2HDL 语言与验证实验报告

一、自定 FSM 说明 1、状态描述 State0&#xff1a;睡觉&#xff0c;如果闹钟响则起床吃早餐&#xff0c;否则继续睡觉 State1&#xff1a;吃早餐&#xff0c;吃完去上课 State2&#xff1a;上课&#xff0c;上完课后如果要开会就去开会&#xff0c;否则去自习 State3&…

LiveGBS国标GB/T28181视频流媒体平台-功能视频集中录制存储云端录像H264|H265|HEVC视频存储

LiveGBS国标GB/T28181视频流媒体平台-视频集中录制存储云端录像H264|H265|HEVC视频存储1、云端录像存储2、手动配置录像2.1、按需录像2.2、一直录像3、录像计划3.1、录像计划入口3.2、新增录像计划3.3、编辑录像计划3.4、关联通道4、查看云端录像4.1、查看录像4.1.1、时间轴模式…

vue路由文件拆分管理

随着项目的原来越大&#xff0c;路由越来越多&#xff0c;我们的路由也会越来越多&#xff0c;如果都集中在一个文件中&#xff0c;会很冗杂文件很长。这时候我们可以将路由文件拆分&#xff0c;可读、方便管理。多人合作添加路由也能更多的避免代码冲突 代码拆分目录如图&…

18 客户端服务发现源码分析

Nacos客户端服务发现源码分析 总体流程 首先我们先通过一个图来直观的看一下&#xff0c;Nacos客户端的服务发现&#xff0c;其实就是封装参数、调用服务接口、获得返回实例列表。 但是如果我们要是细化这个流程&#xff0c;会发现不仅包括了通过NamingService获取服务列表&…

运筹系列79:使用Julia进行column generation求解

1. 案例建模 我们对cutting stock问题进行建模。rolls的尺寸为W&#xff0c;每个型号的需求量和尺寸分别为d和w&#xff0c;如下&#xff1a; struct Piecew::Float64d::Int endstruct Datapieces::Vector{Piece}W::Float64 endfunction Base.show(io::IO, d::Data)println(i…

hls.js如何播放m3u8文件(实例)?

HLS&#xff08;HTTP Live Streaming&#xff09;是一种视频流传输协议&#xff0c;是苹果推出的适用于iOS与macOS平台的流媒体传输协议。它将视频分割成若干个小段&#xff0c;每个小段大小一般为2~10秒不等&#xff0c;并通过HTTP协议进行传输。通过在每个小段之间插入若干秒…

C++学习笔记-多线程

传统的C&#xff08;C11之前&#xff09;中并没有引入线程这个概念&#xff0c;在C11出来之前&#xff0c;如果我们想要在C中实现多线程&#xff0c;需要借助操作系统平台提供的API&#xff0c;比如Linux的<pthread.h>&#xff0c;或者windows下的<windows.h> 。 …

数据结构——链表讲解(1)

作者&#xff1a;几冬雪来 时间&#xff1a;2023年3月3日 内容&#xff1a;数据结构链表讲解 目录 前言&#xff1a; 链表的概念&#xff1a; 1.为什么要有链表&#xff1a; 2.链表的运行原理&#xff1a; 3.链表的形态多少&#xff1a; 4.单链表的代码书写&#xff1…

QML定时器

QML使用Timer使用定时器 Timer 计时器可用于触发操作一次&#xff0c;或以给定的间隔重复触发。 常用属性&#xff1a; interval 设置触发器之间的间隔&#xff08;以毫秒为单位&#xff09;。 默认间隔为 1000 毫秒。 repeat 设置重复&#xff0c;为真&#xff0c;则以指定的…

【力扣】stack容器的探索之有效的括号

作者&#xff1a;狮子也疯狂 专栏&#xff1a;《算法详解》 愿你生如夏花之绚烂&#xff0c;幸运永远与你相伴&#xff0c;疯狂常在。 目录一. &#x1f981; Stack容器的来历1.1 操作栈的方法二. &#x1f981; Stack的使用2.1 题目2.2 分析2.3 详细算法实现2.4 力扣AC截图三…

vscode与C++安装与使用【不好用来骂我】

网上教程很多&#xff0c;但是都不太好用&#xff0c;这是我垃圾堆里淘金淘出来的教程&#xff1a; 安装软件 安装 Visual Studio Code: 你需要下载并安装 Visual Studio Code&#xff0c;可以在官网下载 https://code.visualstudio.com/download。 安装 C 扩展: 在 Visual S…

【基础算法】单链表的OJ练习(2) # 链表的中间结点 # 链表中倒数第k个结点 #

文章目录前言链表的中间结点链表中倒数第k个结点写在最后前言 对于单链表的OJ练习&#xff0c;需要深刻理解做题的思路&#xff0c;这样我们才能够在任何场景都能够熟练的解答有关链表的问题。 关于OJ练习&#xff08;1&#xff09;&#xff1a;-> 传送门 <-&#xff0c…

支持向量机简单介绍

1.概述 支持向量机&#xff08;SVM&#xff0c;支持向量网络&#xff09;&#xff0c;是机器学习中获得关注最多的算法没有之一。它源于统计学习理论。 | | | 功能有监督学习线性二分类与多分类&#xff08;Linear Support Vector Classification&#xff09;非线性二分类与多…