JVM面试连环炮:你准备好迎接挑战了吗?
在Java开发领域,JVM面试一直是一个热门话题。作为一名优秀的开发者,你是否已经准备好迎接这场挑战了呢?今天,我们就来深度解析一下JVM面试的热点问题,帮助你更好地应对面试,一举拿下offer!
1、说一下 JVM 的主要组成部分及其作用?

JVM包含两个子系统和两个组件,两个子系统为Class loader(类装载)、Execution engine(执行引擎);两个组件为Runtime data area(运行时数据区)、Native Interface(本地接口)。
- Class loader(类装载):根据给定的全限定名类名(如:java.lang.Object)来装载class文件到 Runtime data area中的method area。
- Execution engine(执行引擎):执行classes中的指令。
- Native Interface(本地接口):与native libraries交互,是其它编程语言交互的接口。
- Runtime data area(运行时数据区域):这就是我们常说的JVM的内存。
作用:
在Java程序的执行过程中,首先会通过编译器将Java源代码转换成一种叫做字节码(Bytecode)的中间形式。这种字节码是一种平台无关的二进制代码,它比Java源代码更接近于机器语言,但仍然包含了一些用于定位和操作数据结构的指令。
然后,类加载器(ClassLoader)会负责将这种字节码加载到内存中。这个过程通常是动态进行的,也就是说,当程序需要使用某个类的时候,类加载器就会将这个类的字节码加载到内存中。这个过程通常发生在Java虚拟机(JVM)的运行时数据区(Runtime Data Area)的方法区内。
需要注意的是,虽然字节码文件是JVM的一套指令集规范,但它并不能直接交给底层操作系统去执行。这是因为不同的操作系统可能对同一组字节码有不同的解释方式,因此需要一个专门的命令解析器执行引擎(Execution Engine)来将字节码翻译成底层系统可以执行的指令。
最后,Java程序中还可以调用其他语言编写的本地库接口(Native Interface),进行一些系统调用或者C函数调用。这种方式可以使Java程序更好地利用底层系统的功能,提高程序的性能和效率。
下面是ava程序运行机制详细说明
Java程序运行机制步骤:
- 首先利用IDE集成开发工具编写Java源代码,源文件的后缀为.java;
- 再利用编译器(javac命令)将源代码编译成字节码文件,字节码文件的后缀名为.class;
- 运行字节码的工作是由解释器(java命令)来完成的。

从上图中可以观察到,Java文件经过编译器的处理后,被转换成了对应的.class文件。接下来,类加载器会负责将这些.class文件加载到Java虚拟机(JVM)中。
实际上,类的加载过程可以用一句话来概括:类的加载是将类的二进制数据从.class文件中读取出来,并将其放入内存中的运行时数据区的方法区内。然后,在堆区创建一个java.lang.Class对象,用于封装类在方法区内的数据结构。
通过类加载器的作用,JVM能够动态地加载和卸载类,使得程序可以在运行时动态地获取和使用类。这种动态性是Java语言的一大特点,它赋予了程序更高的灵活性和扩展性。
2、说一下JVM运行时数据区?
Java虚拟机在执行Java程序的过程中,会将其管理的内存区域划分为多个不同的数据区域。每个数据区域都有特定的用途,并且它们的创建和销毁时间也不同。
首先,Java虚拟机将内存区域划分为堆(Heap)、方法区(Method Area)和栈(Stack)。
-
堆:堆是Java虚拟机所管理的最大的数据区域。它用于存储对象实例以及数组。当创建一个新的对象时,会在堆上分配相应的内存空间。而当一个对象不再被引用时,垃圾回收器会负责将其所占用的内存释放回堆中。堆的大小可以通过JVM的参数进行设置,例如-Xmx和-Xms分别表示最大堆大小和初始堆大小。
-
方法区:方法区是用于存储类信息、常量池、静态变量等数据的一块内存区域。它与Java类相关联,因为每个Java类都包含方法区的一份拷贝。方法区的生命周期与Java虚拟机的生命周期一致,因此随着虚拟机进程的启动而存在。
-
栈:栈是Java虚拟机用来支持函数调用和方法执行的数据结构。每个线程在创建时都会创建一个独立的栈,其中存储着局部变量、操作数栈和返回地址等信息。栈的特点是后进先出(LIFO),即最后进入栈的元素会最先被取出。栈的生命周期与线程的生命周期一致,因此依赖于线程的启动和结束来建立和销毁。
除了这些主要的数据区域外,Java虚拟机还可能划分其他一些辅助的区域,例如程序计数器(Program Counter Register)和本地方法栈(Native Method Stack)等。这些区域的具体用途和生命周期取决于Java虚拟机的实现和运行环境。
- 程序计数器(Program Counter Register):当前线程所执行的字节码的行号指示器,字节码解析器的工作是通过改变这个计数器的值,来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能,都需要依赖这个计数器来完成;
- 本地方法栈(Native Method Stack):与虚拟机栈的作用是一样的,只不过虚拟机栈是服务 Java方法的,而本地方法栈是为虚拟机调用 Native 方法服务的;

3、什么是堆内存?
以Hotspot为例,堆内存(HEAP)主要由GC模块进行分配和管理, 可分为以下部分:
- 新生代(伊甸园区+幸存者区)
- 老年代
我们在jvm参数中只要使用-Xms,-Xmx等参数就可以设置堆的大小和最大值,理解jvm的堆还需要知道下面这个公式:
堆内内存 = 新生代+老年代。如下面的图所示:

在使用堆内内存(on-heap memory)的时候,完全遵守JVM虚拟机的内存管理机制,采用垃圾回收器(GC)统一进行内存管理,GC会在某些特定的时间点进行一次彻底回收,也就是Full GC,GC会对所有分配的堆内内存进行扫描,在这个过程中会对JAVA应用程序的性能造成一定影响,还可能会产生Stop The World。
常见的垃圾回收算法主要有:
- 引用计数器法(Reference Counting)
- 标记清除法(Mark-Sweep)
- 复制算法(Coping)
- 标记压缩法(Mark-Compact)
- 分代算法(Generational Collecting)
4、什么是堆外内存?
堆外内存,也常被称为直接内存,是Java虚拟机管理内存的一种方式。与Java虚拟机的堆内存相对应,堆外内存是将内存对象分配在Java虚拟机的堆以外的内存区域。这部分内存并不受Java虚拟机的管理,而是直接由操作系统进行操作和管理。
这种设计的主要优点是能够在一定程度上减少垃圾回收对应用程序造成的影响。因为堆外内存的分配和释放不依赖于Java虚拟机的垃圾回收机制,所以它可以更快速地进行内存的分配和释放,从而提高应用程序的性能。
作为Java开发者,我们经常使用java.nio.DirectByteBuffer类来管理堆外内存。这个类的实例会在对象创建的时候自动分配堆外内存。DirectByteBuffer类提供了一种在Java堆外分配内存的方式,它主要是通过其成员变量unsafe来进行操作的。
5、使用堆外内存的优点
- 减少了垃圾回收, 因为垃圾回收会暂停其他的工作。
- 加快了复制的速度,堆内在flush到远程时,会先复制到直接内存(非堆内存),然后在发送;而堆外内存相当于省略掉了这个工作。
6、简述Java垃圾回收机制
在Java编程中,程序员并不需要显式地释放对象的内存,这是由Java虚拟机(JVM)自动完成的。当一个对象不再被任何变量引用时,它就会被视为“垃圾”,并被标记为可回收的内存。然后,JVM会定期运行垃圾回收线程来检查这些垃圾对象,并将它们从内存中清除。
这个垃圾回收线程在JVM中的优先级是低的,这意味着它不会在程序运行过程中频繁地执行。相反,它会在JVM认为合适的时候执行。例如,当JVM的空闲时间超过一定阈值时,或者当堆内存的使用率达到一定限制时,垃圾回收线程就会被触发。
垃圾回收线程的工作过程是这样的:首先,它会扫描所有的对象,找出那些没有被任何其他变量引用的对象。这些对象就被称为“垃圾”。然后,它将这些垃圾对象添加到一个称为“垃圾回收集合”的数据结构中。最后,它会从内存中彻底清除这些垃圾对象,释放它们占用的内存空间。
总的来说,Java程序员不需要担心内存管理问题,因为JVM会自动处理这些问题。这大大简化了编程的复杂性,使得程序员可以更专注于实现具体的功能,而不是管理内存。
7、哪些对象会被存放到老年代?
- 新生代对象每次经历⼀次minor gc,年龄会加1,当达到年龄阈值(默认为15岁)会直接进⼊老年代;
- 大对象直接进⼊老年代;
- 新生代复制算法需要⼀个survivor区进行轮换备份,如果出现大量对象在minor gc后仍然存活的情况时,就需要老年代进行分配担保,让survivor⽆法容纳的对象直接进⼊老年代;
- 如果在Survivor空间中相同年龄所有对象大⼩的总和大于Survivor空间的⼀半,年龄大于或等于该年龄的对象就可以直接进⼊年⽼代。
8、什么时候触发full gc?
- 调用System.gc时,系统建议执行Full GC,但是不必然执行
- 老年代空间不⾜
- 方法区空间不⾜
- 通过Minor GC后进入老年代的平均大小大于老年代的可用内存
- 由Eden区、From Space区向To Space区复制时,对象大小大于To Space可用内存,则把该对象转存到老年代,且老年代的可用内存小于该对象大小
相关文章:
JVM面试连环炮:你准备好迎接挑战了吗?
在Java开发领域,JVM面试一直是一个热门话题。作为一名优秀的开发者,你是否已经准备好迎接这场挑战了呢?今天,我们就来深度解析一下JVM面试的热点问题,帮助你更好地应对面试,一举拿下offer! 1、…...
Ansible通过kubernetes.core.k8s_info和kubernetes.core.k8s访问OCP
文章目录 环境OCPClient(Ansible控制节点) 步骤准备工作在client端配置ssh免密登录OCP端在client端安装Ansible kubernetes.core.k8s_info第1次尝试在OCP端安装python和pip3在OCP端安装kubernetes在OCP端安装PyYAML第2次尝试在OCP端配置config文件第3次尝…...
vscode汉化
安装插件 Chinese (Simplified) (简体中文) Language Pack for 重新打开,若还是没有汉化: 【CtrlShiftp】 输入“configure display language”,回车键 选择刚刚安装的 中文(简体)...
美易投资:美国圣诞树价格飙升,涨价的问题所在?
美国圣诞树价格飙升,商家称“拜登经济学”是导致涨价的罪魁祸首 随着圣诞节的临近,美国各地的家庭开始准备庆祝这一传统佳节。然而,今年美国的圣诞树价格却呈现出了明显的上涨趋势。据一些商家反映,这主要是由于“拜登经济学”所致…...
国内外聊天AI大比拼,你知道几个?一键了解最火聊天AI应用!
国内类ChatGPT的AI工具一网打尽 2022年,是一个不平凡的一年。ChatGPT迅速崭露头角,成为备受瞩目的热门话题。特别是在OpenAI发布了基于GPT-3.5模型的ChatGPT版本后,这一产品因其卓越的对话能力和广泛的应用潜力,很快引起了大众的…...
C++STL的vector模拟实现
文章目录 前言成员变量成员函数构造函数push_backpop_backinserterase析构函数拷贝构造 前言 成员变量 namespace but {template<class T>class vector{public:typedef T* iterator;private:iterator _start;iterator _finish;iterator _end_of_storage;}; }我们之前实…...
openssl 常用命令 pkcs12
openssl pkcs12 openssl pkcs12 官方文档 1. 描述 The pkcs12 command allows PKCS#12 files (sometimes referred to as PFX files) to be created and parsed. PKCS#12 files are used by several programs including Netscape, MSIE and MS Outlook. pkcs12 命令是用来创…...
2017下半年软工(桥接模式)
题目——桥接模式(抽象调用实现部分) package org.example.桥接模式;/*** 桥接模式的核心思想是将抽象部分与它的实现部分分离,使它们可以独立变化,就是说你在实现部分:WinImp、LinuxImp基础上还能加上RedHatImp&#…...
Hive 浅析
Hive是一个简单的LUA沙盒,除了基本的LUA解释器的功能以外,还提供了诸如热加载等功能。 了解HIVE的工作原理有利于了解Lua虚拟机的底层实现机理。 本文从是什么-怎么用-为什么三个维度介绍HIVE。 Hive Hive是什么 hive是一个简单的LUA应用框架,目前基于…...
C 语言中,结构体「.」与「->」的区别
简单来说 「 」的左边是结构体名字时用点符号「.」 「 」的左边是结构体指针时名字时用箭头「->」 对于要读取结构体种的数据时,有下面三种写法,操作是等价的。 struct ListNode a;struct ListNode *p1 &a;/*三种写法*/a.element 2333;p1->e…...
【Java Web学习笔记】5 - XML
项目代码 https://github.com/yinhai1114/JavaWeb_LearningCode/tree/main/xml 零、在线文档 XML系列教程 一、XML引出 1.为什么需要XML 1.需求1 :两个程序间进行数据通信? 2.需求2:给一台服务器,做一个配置文件,当服务器程序启动时,去…...
在jupyter notebook中修改其他文件的解决方案
大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…...
如何在Android中旋转屏幕时避免重新绘制Activity
如何在Android中旋转屏幕时避免重新绘制Activity 在Android开发中,设备旋转通常导致当前活动(Activity)被销毁并重新创建,这可能导致用户界面重置和不必要的资源重新加载。然而,有时我们希望避免这种行为,…...
离线环境下安装python库(推荐pip download)
离线环境下安装python库(推荐pip download) 目录 1.需求 2.失败操作(注意) 3.成功操作 4.其它参考 1.需求 机器部署web系统环境后,就不可再次联网,所以升级python web后端,需要离线安装pyt…...
ubuntu16.04安装ROS+Gazebo
ubuntu16.04安装ROS参考文章 ros安装(一键最简安装,吹爆鱼香ROS,请叫我鱼吹) ROS篇——Ubuntu快速一键安装ROS或ROS2(通用) ubuntu安装ROS melodic(最新、超详细图文教程) 配置ubuntu以及安装ros2必要环…...
手动搭建koa+ts项目框架(路由篇)
文章目录 前言一、安装koa-router二、引入koa-router并使用三、优化路由配置总结如有启发,可点赞收藏哟~ 前言 本文基于手动搭建koats项目框架(基础篇)配置接口路由 一、安装koa-router npm i -S koa-router二、引入koa-router并使用 ./sr…...
c语言:文件操作(1)
前言:为什么要使用文件 使用文件可以让程序在不同运行之间保存和读取数据。这样可以实现持久化存储,即使程序关闭后数据也不会丢失。文件也可以用于数据交换,允许不同程序之间共享信息。在 C 语言中,文件还可以用于读取配置信息&…...
运筹学经典问题(三):最大流问题
问题描述 给定一个图网络 G ( V , E ) G(V, E) G(V,E),网络中连边的权重代表最大容量,在这个图中找出从起点到终点流量最大的路径。 数学建模 集合: I I I:点的集合; E E E:边的集合。 常量&#x…...
裸机开发与Linux驱动开发的区别
一. 简介 裸机开发,即我们常说的不带系统的单片机开发。 Linux驱动开发,即带文件系统的Linux驱动的开发。 二. 裸机开发与Linux驱动开发的区别 1. 裸机开发 比较底层,跟寄存器打交道,有些 MCU提供了库。 2. Linux驱动开发…...
【蓝桥杯选拔赛真题75】Scratch行走的螃蟹 第十五届蓝桥杯scratch图形化编程 少儿编程创意编程选拔赛真题解析
目录 scratch行走的螃蟹 一、题目要求 编程实现 二、案例分析 1、角色分析...
HTML 语义化
目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案: 语义化标签: <header>:页头<nav>:导航<main>:主要内容<article>&#x…...
1.3 VSCode安装与环境配置
进入网址Visual Studio Code - Code Editing. Redefined下载.deb文件,然后打开终端,进入下载文件夹,键入命令 sudo dpkg -i code_1.100.3-1748872405_amd64.deb 在终端键入命令code即启动vscode 需要安装插件列表 1.Chinese简化 2.ros …...
uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
Yolov8 目标检测蒸馏学习记录
yolov8系列模型蒸馏基本流程,代码下载:这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中,**知识蒸馏(Knowledge Distillation)**被广泛应用,作为提升模型…...
【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)
本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...
Redis:现代应用开发的高效内存数据存储利器
一、Redis的起源与发展 Redis最初由意大利程序员Salvatore Sanfilippo在2009年开发,其初衷是为了满足他自己的一个项目需求,即需要一个高性能的键值存储系统来解决传统数据库在高并发场景下的性能瓶颈。随着项目的开源,Redis凭借其简单易用、…...
【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案
目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后,迭代器会失效,因为顺序迭代器在内存中是连续存储的,元素删除后,后续元素会前移。 但一些场景中,我们又需要在执行删除操作…...
Vue ③-生命周期 || 脚手架
生命周期 思考:什么时候可以发送初始化渲染请求?(越早越好) 什么时候可以开始操作dom?(至少dom得渲染出来) Vue生命周期: 一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个…...
Oracle11g安装包
Oracle 11g安装包 适用于windows系统,64位 下载路径 oracle 11g 安装包...
Ubuntu系统复制(U盘-电脑硬盘)
所需环境 电脑自带硬盘:1块 (1T) U盘1:Ubuntu系统引导盘(用于“U盘2”复制到“电脑自带硬盘”) U盘2:Ubuntu系统盘(1T,用于被复制) !!!建议“电脑…...
