08-JVM 面试题-mk

文章目录

  • 1.JVM 的各部分组成
  • 2.运行时数据区
    • 2.1.什么是程序计数器?
    • 2.2.你能给我详细的介绍Java堆吗?
    • 2.3.能不能解释一下方法区?
      • 2.3.1常量池
      • 2.3.2.运行时常量池
    • 2.4.什么是虚拟机栈?
      • 2.4.1.垃圾回收是否涉及栈内存?
      • 2.4.2.栈内存分配越大越好吗?
      • 2.4.3.方法内的局部变量是否线程安全?
      • 2.4.4.什么情况下会导致栈内存溢出?
  • 3.你听过直接内存吗?
  • 4.什么是类加载器,类加载器有哪些?
    • 4.1.什么是类加载器
    • 4.2.类加载器有哪些?
    • 4.3.什么是双亲委派模型?
    • 4.4JVM为什么采用双亲委派机制?
  • 5.说一下类装载的执行过程?
  • 6.对象什么时候可以被垃圾器回收 ?
    • 6.1.引用计数法
    • 6.2.可达性分析算法
  • 7.JVM 垃圾回收算法有哪些?
    • 7.1.标记清除算法
    • 7.2.标记整理算法
    • 7.3.复制算法
  • 8.说一下JVM中的分代回收
    • 8.1.分代收集算法
    • 8.2.MinorGC、 Mixed GC 、 FullGC的区别是什么
  • 9.说一下JVM有哪些垃圾回收器?
    • 9.1.串行垃圾收集器
    • 9.2.并行垃圾收集器
    • 9.3.CMS(并发)垃圾收集器
    • 9.4.详细聊一下G1垃圾回收器
  • 10.强引用、软引用、弱引用、虚引用的区别?
  • 11.JVM 调优的参数可以在哪里设置参数值
    • 11.1.war包部署在tomcat中设置
    • 11.2.jar包部署在启动参数设置
  • 12.什么时候用到 JVM 调优,调优哪些参数?
  • 13.JVM 调优的参数都有哪些?
    • 13.1.设置堆空间大小(放对象和数组)
    • 13.2.虚拟机栈的设置
    • 13.3.年轻代中Eden区和两个Survivor区的大小比例
    • 13.4.年轻代晋升老年代阈值
    • 13.5.设置垃圾回收收集器
  • 14.说一下 JVM 调优的工具?
  • 15.Java内存泄露的排查思路
  • 16.CPU飙高排查方案与思路
  • 17.cpu 比较低,load 比较高怎么解决

1.JVM 的各部分组成

知道JVM 的好处:知道java 运行机制,排查问题的能力增加,比如内存泄漏、CPU飙高

JVM 是什么:Java Virtual Machine缩写,Java程序的运行环境(java二进制字节码的运行环境)

好处

  • 一次编写,到处运行
  • 自动内存管理,垃圾回收机制

在这里插入图片描述

从图中可以看出 JVM 的主要组成部分

  • ClassLoader(类加载器):负责将 .class 文件加载到 JVM 中,并转换为运行时数据结构(Class 对象)
  • Runtime Data Area(运行时数据区):管理程序运行时的内存分配和数据存储
  • Execution Engine(执行引擎):把字节码翻译为底层系统指令
    • 解释器:解释字节码信息
    • 即时编译器:针对代码进行优化
    • GC:主要是指运行数据区中的堆空间
  • Native Method Library(本地库接口):由C或C++实现,因为Java代码并不能实现某些功能,需要借助系统提供的接口(本地方法接口)

重点讲解下面部分:

JVM组成:重点介绍运行数据区

类加载器:主要指类加载子系统(比如:一个类的生命周期是什么、常见的类加载器有哪些)

垃圾回收:主要指的是堆中的对象垃圾回收,包含了垃圾回收算法、垃圾回收器、怎么去设置

JVM实践:JVM 调优的一些内容,比如参数怎么设置,该设置多少?出错了怎么办?比如内存泄漏问题、CPU飙高问题

2.运行时数据区

管理程序运行时的内存分配和数据存储
在这里插入图片描述
分为以下部分

  1. 线程共享区域

    • 方法区(Method Area)
      • 存储类的元数据(类名、类的结构、方法信息、字段信息)、静态变量、常量池等。
      • JDK 8 后由元空间(Metaspace)实现,直接使用本地内存。
    • 堆(Heap)
      • 存储所有对象实例和数组,是垃圾回收(GC)的主要区域。
      • 分为新生代(Eden、Survivor区)和老年代。
  2. 线程私有区域

  • 虚拟机栈(JVM Stack)
    • 每个方法调用对应一个栈帧(存储局部变量表、操作数栈、动态链接、方法出口)。
    • 栈深度超出限制时抛出 StackOverflowError。
  • 本地方法栈(Native Method Stack)
    • 为 Native 方法(如 C/C++ 实现的方法)服务。
  • 程序计数器(Program Counter Register)
    • 记录当前线程执行的字节码指令地址(分支、循环、异常处理依赖此区域)。

2.1.什么是程序计数器?

属于运行数据区的一部分,是线程私有的(没有线程安全问题),每个线程都有一份,内部保存的字节码的行号。用于记录正在执行的字节码指令的地址

javap -v xx.class 打印每个方法的详细信息,包括字节码指令(操作码)、局部变量表、操作数栈等。
在这里插入图片描述
什么是程序计数器?

属于运行数据区的一部分,是线程私有的(没有线程安全问题),每个线程都有一份,内部保存的字节码的行号。用于记录正在执行的字节码指令的地址

2.2.你能给我详细的介绍Java堆吗?

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

下图是运行数据区
在这里插入图片描述
S0、S1也被成为幸存者区 ,一个对象来了之后先会到Eden(伊甸)区,假如这个对象在垃圾回收之后还存活,就会被复制移动到S0或者S1,假如对象移动一定次数还存活着,就会被放到老年代中,老年代是指生命周期比较长的

  1. 年轻代被划分为三部分,Eden区和两个大小严格相同的Survivor区,根据JVM的策略,在经过几次垃圾收集后,任然存活于Survivor的对象将被移动到老年代区间。
  2. 老年代主要保存生命周期长的对象,一般是一些老的对象
  3. 元空间(方法区)保存的类名、类的结构、方法信息、字段信息、静态变量、常量池等

java1.7和java1.8 堆的区别是什么?

在java1.8 之前,堆中有个永久代概念,和元空间的作用是一样的。因为元空间或方法区,主要存储的是一些类或者常量,随着项目类加载越来越多,java 1.7的永久代不可控,如果设置小了,就会存在内存溢出,设置大了会浪费内存,java1.8做了优化,都放到本地内存,这样堆节省空间,防止内存溢出,避免OOM。

在这里插入图片描述
你能给我详细的介绍Java堆吗?

  • 线程共享的区域:主要用来保存对象实例,数组等,内存不够则抛出OutOfMemoryError异常。
  • 组成:年轻代+老年代
    • 年轻代被划分为三部分,Eden区和两个大小严格相同的Survivor区
    • 老年代主要保存生命周期长的对象,一般是一些老的对象
  • Jdk1.7和1.8的区别
    • 1.7中有有一个永久代,存储的是类名、类的结构、方法信息、字段信息、静态变量、常量池等
    • 1.8移除了永久代,把数据存储到了本地内存的元空间中,防止内存溢出

2.3.能不能解释一下方法区?

属于运行数据区的一部分

  • 方法区(Method Area)是各个线程共享的内存区域
  • 存储类的元数据(类名、类的结构、方法信息、字段信息)、静态变量、常量池等
  • 虚拟机启动的时候创建,关闭虚拟机时释放
  • 如果方法区域中的内存无法满足分配请求,则会抛出OutOfMemoryError: Metaspace

在这里插入图片描述

方法区逻辑上属于堆的一部分,但是不同厂商,存储的位置不一样,我们现在用的时oracle 提供的hotpot 虚拟机,在JDK8 之前,方法区是存在堆中一个叫永久代这个区域中,在JDK8 之后,把永久代给移除了,换了一个实现,这个实现叫做元空间,元空间不在堆内存中,用的是本地内存,也就是操作系统内存,为什么会挪动?避免OOM

  • Class:类的信息,包括了类名、类的结构、方法、字段等
  • Classloader:来加载这个类

2.3.1常量池

可以看作是一张表,虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面量等信息
javap -v Application.class ,查看字节码结构(类的基本信息、常量池、方法定义)

下图,左侧是main方法的指令信息,右侧constant pool 是常量池,main方法按照指令执行的时候,需要到常量池中查表翻译找到具体的类和方法地址去执行
在这里插入图片描述

2.3.2.运行时常量池

常量池是 *.class 文件中的,当该类被加载,它的常量池信息就会放入运行时常量池,并把里面的符号地址变为真实地址 (真正的内存地址)
在这里插入图片描述
能不能解释一下方法区?

  • 方法区(Method Area)是各个线程共享的内存区域
  • 主要存储类名、类的结构、方法信息、字段信息、静态变量、常量池
  • 虚拟机启动的时候创建,关闭虚拟机时释放
  • 如果方法区域中的内存无法满足分配请求,则会抛出OutOfMemoryError: Metaspace

介绍一下运行时常量池

  • 常量池:可以看作是一张表,虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面量等信息
  • 当类被加载,它的常量池信息就会放入运行时常量池,并把里面的符号地址变为真实地址

2.4.什么是虚拟机栈?

Java Virtual machine Stacks (java 虚拟机栈)

  • 每个线程运行时所需要的内存,称为虚拟机栈(多个线程也会创建多个虚拟机栈,是线程私有、线程安全的),先进后出(什么时候创建虚拟机栈?
  • 每个栈由多个栈帧(frame)组成(方法会调用其它方法,产生多个栈帧),对应着每次方法调用时所占用的内存(每个栈帧包含方法所需要的数据,比如参数、局部变量、返回地址
  • 每个线程只能有一个活动栈帧,对应着当前正在执行的那个方法

在这里插入图片描述

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

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

2.4.2.栈内存分配越大越好吗?

未必,默认的栈内存通常为1024k,栈帧过大会导致线程数变少(每个线程都会创建虚拟机栈),例如,机器总内存为512m,目前能活动的线程数则为512个,如果把栈内存改为2048k,那么能活动的栈帧(或者线程)就会减半

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

  • 如果方法内局部变量没有逃离方法的作用范围,它是线程安全的
  • 如果是局部变量引用了对象(形参StringBuilder),并逃离方法的作用范围,需要考虑线程安全

m1方法线程安全,m2 和m3 方法不安全

m1:每个线程来了之后,都会创建栈帧,每个栈帧都会有局部变量sb,每个线程都是独有的,并没有线程安全问题

m2:形参sb也是局部变量,在参数传递过程中,有可能会被其它线程操作。比如主线程中创建了一个StringBuilder对象sb,又在新线程里面把sb作为参数传给了m2方法,主线程和新线程都在修改sb,sb是主线程和新线程共享的,线程不安全。

m3:会把局部变量返回,这个局部变量有可能会被其它线程共用,可以在mian 方法中调用m3 方法,得到局部变量,然后在mian 方法中开启多线程同时去操作这个变量,也成了多个线程共用的变量
在这里插入图片描述

2.4.4.什么情况下会导致栈内存溢出?

  • 栈帧过多导致栈内存溢出(java.lang.StackOverflowError),典型问题:递归调用
  • 栈帧过大导致栈内存溢出(1M内存,不太容易出现)
public static void m4()
{m4();
}

1.什么是虚拟机栈

  • 每个线程运行时所需要的内存,称为虚拟机栈,它是先进后出的特点
  • 每个栈由多个栈帧(frame)组成,对应着每次方法调用时所占用的内存
  • 每个线程只能有一个活动栈帧,对应着当前正在执行的那个方法

2.垃圾回收是否涉及栈内仔?

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

3.栈内存分配越大越好吗?

  • 未必,默认的栈内存通常为1024K,栈帧过大会导致线程数变少

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

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

5.什么情况下会导致栈内存溢出?

  • 栈帧过多导致栈内存溢出,典型问题:递归调用
  • 栈帧过大导致栈内存溢出

6.堆和栈的区别是什么?

  • 栈内存一般会用来存储方法调用的栈帧、局部变量、操作数栈等,但堆内存是用来存储Java对象和数组的。堆会GC垃圾回收,而栈不会。
  • 栈内存是线程私有的,而堆内存是线程共有的。
  • 两者异常错误不同,但如果栈内存或者堆内存不足都会抛出异常。
    • 栈空间不足:java.lang.StackOverFlowError。
    • 堆空间不足:java.lang.OutOfMemoryError。

3.你听过直接内存吗?

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

java 本身不具有磁盘读写能力,要调用磁盘读写,必须调用操作系统提供的函数,会调用本地的方法,native 修饰的方法都是操作系统提供的方法,使用native 修饰的方法去操作磁盘文件。 这里涉及到CPU的运行状态,会从java 的 用户态切换到内核态,这是CPU状态的改变,其次内存也有一系列操作,当切换到内核态之后,会由CPU 的函数读取磁盘文件,会在操作系统中划出一块缓冲区,这个缓冲区我们也称为系统缓存区,磁盘内容会读到系统缓存区中,它不能把几百兆的数据一次性全部读到系统缓存区中,会利用缓冲区分批次进行读取,读到系统的缓存区,这个系统缓冲区,我们java 代码是不能操作的,java 会在堆中分配一块内存,对应代码中 new byte[] ,会划分java 的缓冲区,我们代码要想访问刚才读到的流中数据,必须要从系统的缓存区读到java 的缓冲区,读到java 的缓冲区会进入java 的下一个状态(用户态),会调用输出流的写入操作,这样反复进行读写,这个文件会复制到目标位置。也发现问题所在,有两个缓冲区,有两块内存,一个是系统提供的系统缓存区,另一个是java 的缓冲区,读取数据的时候,数据要存两份,第一次读到系统缓冲区,第二次读到java 缓冲区,因为java 代码访问不了系统缓冲区,必须读到java 缓冲区之后,java 代码才能进行操作,这就造成不必要的数据复制,因此效率不是很高

在这里插入图片描述
NIO

操作系统中划出了一块缓冲区,这个区域叫直接内存,系统也可以访问,java 代码可以直接访问。磁盘文件读写的时候,java 代码操作非常方便,比IO少了一次缓冲区的复制操作,所以说速度成倍的提升
在这里插入图片描述
你听过直接内存吗?

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

4.什么是类加载器,类加载器有哪些?

  • 类加载器:负责将 .class 文件加载到 JVM 中,并转换为运行时数据结构(Class 对象)
  • 运行时数据区:管理程序运行时的内存分配和数据存储
  • 执行引擎:执行字节码文件或本地方法,把字节码翻译为底层系统指令
  • 垃圾回收器:用于对JVM中的垃圾内容进行回收

在这里插入图片描述
什么是类加载器,类加载器有哪些 ?

类加载器:JVM只会运行二进制文件,负责将 .class 文件加载到 JVM 中,并转换为运行时数据结构(Class 对象),从而让Java程序能够启动起来。

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

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

相关文章

Vue3 nextTick

nextTick 是 Vue 中非常重要的一个 API&#xff0c;它允许你在 DOM 更新周期后执行延迟回调。 核心源码位置 Vue3 的 nextTick 实现主要在 packages/runtime-core/src/scheduler.ts 文件中。 基本实现 const resolvedPromise Promise.resolve() as Promise<any> let …

DISCO:利用大型语言模型提取反事实

DISCO: Distilling Counterfactuals with Large Language Models - ACL Anthologyhttps://aclanthology.org/2023.acl-long.302/ 1. 概述 尽管在自然语言处理(NLP)领域针对各种推理任务取得了巨大进展(Wang 等, 2018, 2019a;Xu 等, 2020),但数据集偏差仍然是构建鲁棒模型…

【Django】框架-路由系统核心概念解析

1. 最基本路由关系 路由是URL地址与处理逻辑&#xff08;视图函数&#xff09;的对应关系。 本质&#xff1a;将用户请求的URL路径映射到具体的处理程序&#xff08;如Django视图函数&#xff09;。 示例&#xff1a; # urls.py urlpatterns [ path(home/, views.home_…

理解 results = model(source, stream=True) 的工作原理和优势

1. 核心概念解析 (1) streamTrue 的作用 生成器模式&#xff1a;当处理视频或图像序列时&#xff0c;streamTrue 会将结果包装成一个 生成器&#xff08;Generator&#xff09;&#xff0c;逐帧生成 Results 对象&#xff0c;而不是一次性返回所有结果。内存优化&#xff1a;…

重新定义“边缘”:边缘计算如何重塑人类与数据的关系

在数字化浪潮中&#xff0c;云计算曾是科技界的宠儿&#xff0c;但如今&#xff0c;边缘计算正在悄然改变游戏规则。它不仅是一种技术进步&#xff0c;更是对人类与数据关系的一次深刻反思。本文将探讨边缘计算如何从“中心化”走向“分布式”&#xff0c;以及它如何在效率、隐…

MCP 协议知识分享

MCP 协议知识分享 一、MCP 协议概述1.1 定义与背景1.2 核心价值1.3 与传统 API 的对比 二、技术架构与工作原理2.1 核心组件2.2 通信机制2.3 典型工作流程 三、关键技术与应用场景3.1 核心技术3.2 典型应用场景 四、与微软技术的集成4.1 Azure OpenAI 服务4.2 Playwright MCP 服…

策略模式实现 Bean 注入时怎么知道具体注入的是哪个 Bean?

Autowire Resource 的区别 1.来源不同&#xff1a;其中 Autowire 是 Spring2.5 定义的注解&#xff0c;而 Resource 是 Java 定义的注解 2.依赖查找的顺序不同&#xff1a; 依赖注入的功能&#xff0c;是通过先在 Spring IoC 容器中查找对象&#xff0c;再将对象注入引入到当…

Linux》》bash 、sh 执行脚本

通常使用shell去运行脚本&#xff0c;两种方法 》bash xxx.sh 或 bash “xxx.sh” 、sh xxx.sh 或 sh “xxx.sh” 》bash -c “cmd string” 引号不能省略 我们知道 -c 的意思是 command&#xff0c;所以 bash -c 或 sh -c 后面应该跟一个 command。

【解析】ReentrantLock锁、Syschronized锁面试点解析

面试官提问 ● 公平锁与非公平锁的区别是什么&#xff1f; ● 什么是可重入锁&#xff1f; ● 什么是死锁&#xff0c;怎样避免死锁&#xff1f; ● ReentrantLock与Syschronized实现原理是什么&#xff1f;两者有什么区别&#xff1f; ● 请说明ReentrantLock获取锁与释放…

04.Python代码NumPy-通过索引或切片来访问和修改

04.Python代码NumPy-通过索引或切片来访问和修改 提示&#xff1a;帮帮志会陆续更新非常多的IT技术知识&#xff0c;希望分享的内容对您有用。本章分享的是Python基础语法。前后每一小节的内容是存在的有&#xff1a;学习and理解的关联性&#xff0c;希望对您有用~ python语法…

跨平台数据采集如何解决不同平台之间的数据兼容性问题?

在数字化时代&#xff0c;企业越来越依赖多个信息系统来管理业务&#xff0c;例如ERP&#xff08;企业资源计划&#xff09;、CRM&#xff08;客户关系管理&#xff09;、财务管理系统、电商平台等。然而&#xff0c;在进行跨平台数据采集时&#xff0c;不同系统之间的数据格式…

解决 vite.config.ts 引入scss 预处理报错

目录 报错1&#xff1a;[plugin:vite:css] [SASS] Error&#xff1a;Cant find stylesheet to import 报错2&#xff1a;[plugin:vite:css] [sass] Error: Undefined variable 版本号&#xff1a; "sass": "^1.86.3","sass-loader": "^1…

C++笔记,数学函数

参考链接&#xff1a;C中数学函数的使用方法_cpp里指数函数-CSDN博客 头文件 <cmath> 1. 基本的算数运算函数 1.1 sqrt() - 计算平方根 功能&#xff1a;计算一个非负实数的平方根。原型&#xff1a;double sqrt(double x);示例代码&#xff1a; #include <iostr…

不关“猫”如何改变外网IP?3种免重启切换IP方案

每次更换外网IP都要重启路由器&#xff1f;太麻烦了&#xff01;那么&#xff0c;不关猫怎么改变外网IP&#xff1f;无论是为了网络调试、爬虫需求&#xff0c;还是解决IP限制问题&#xff0c;频繁重启设备既耗时又影响效率。其实&#xff0c;更换外网IP并不一定要依赖“重启大…

道路运输安全员企业负责人考试内容与范围

道路运输企业主要负责人&#xff08;安全员&#xff09;考证要求 的详细说明&#xff0c;适用于企业法定代表人、分管安全负责人等需取得的 《道路运输企业主要负责人和安全生产管理人员安全考核合格证明》&#xff08;交通运输部要求&#xff09;。 考试内容与范围 1. 法律法…

深入剖析 WiFi 定位解析功能:原理、技术优势与应用场景

WiFi 定位解析功能的原理​ 信号强度与距离的关系​ WiFi 定位的核心原理基于无线信号传播过程中的一个基本特性&#xff1a;信号强度与信号发射源&#xff08;即 WiFi 接入点&#xff0c;Access Point&#xff0c;简称 AP&#xff09;和接收设备之间距离的关联。一般来说&am…

NVIDIA RTX™ GPU 低成本启动零售 AI 场景开发

零售行业正在探索应用 AI 升级客户体验&#xff0c;同时优化内部流程。面对多重应用场景以及成本优化压力&#xff0c;团队可采用成本相对可控的方案&#xff0c;来应对多重场景的前期项目预演和落地&#xff0c;避免短期内大规模投入造成的资源浪费。 客户体验 AI 场景的研究…

首次打蓝桥杯总结(c/c++B组)

目录 一、对每个题进行总结 1.填空题 2.第一个大题---可分解的正整数&#xff08;10--3&#xff09; 3.第二道大题---产值调整&#xff08;10--3&#xff09; 4.第三道大题---画展部署&#xff08;15--7&#xff09; 5.第四道大题---水质检测&#xff08;15--3&#x…

林纳斯·托瓦兹:Linux系统之父 Git创始人

名人说&#xff1a;路漫漫其修远兮&#xff0c;吾将上下而求索。—— 屈原《离骚》 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 林纳斯托瓦兹&#xff1a;Linux之父、Git创始人 一、传奇人物的诞生 1. 早年生活与家…

C语言多进程素数计算

题目描述&#xff1a; 以下代码实现了一个多进程素数计算程序&#xff0c;通过fork()函数创建子进程来并行计算指定范围内的素数。请仔细阅读代码并回答以下问题。 #include "stdio.h" #include "unistd.h" #include <sys/types.h> #include "…