JVM面试基本问题整理

news2024/11/25 18:27:53

文章目录

  • 1、说下对JVM内存模型的理解
  • 2、运行时常量池的位置
  • 3、常量池和运行时常量池的区别
  • 4、内存溢出和内存泄漏
  • 5、Java 对象大小计算
  • 6、GCROOT都有什么
  • 7、常用的JVM启动参数有哪些
  • 8、TLAB

1、说下对JVM内存模型的理解

在这里插入图片描述
1)线程私有区域

  • 程序计数器(Program Counter Register)
    • 作用:记录当前线程正在执行的字节码指令地址
    • 存储内容:当前线程所执行的字节码指令地址。每个线程都有一个独立的程序计数器,用于线程切换后能恢复正确的执行位置。
  • Java 虚拟机栈(Java Virtual Machine Stack)
    • 作用:管理线程的方法调用和执行。
    • 存储内容:栈帧(Stack Frame),包含局部变量表操作数栈动态链接方法出口等信息。每个方法调用都会创建一个栈帧
  • 本地方法栈(Native Method Stack)
    • 作用:管理本地(Native)方法的调用。
    • 存储内容:与 Java 虚拟机栈类似,但用于本地方法的执行。

2)线程共享区域

  • 堆(Heap)
    • 作用:存储所有对象实例和数组。
    • 存储内容:所有对象实例和数组。堆是垃圾收集的主要区域
  • 方法区(Method Area)
    • 作用:存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据。
    • 存储内容:类信息(元数据)、常量池、静态变量、JIT 编译后的代码。
  • 元空间(Metaspace):JDK 8 之后,方法区改为使用本地内存的元空间来存储类元数据。
  • 运行时常量池(Runtime Constant Pool)
    • 作用:存储编译期生成的各种字面量和符号引用。
    • 存储内容:字面量、符号引用。这部分内容是方法区的一部分,但因为其重要性,通常单独列出。JDK 8 及之后挪到了堆中。

2、运行时常量池的位置

  • JDK 7 之前:
    运行时常量池位于永久代中。
    永久代存储类元数据、常量池、静态变量、类方法等。
  • JDK 7:
    运行时常量池从永久代移到了中。
    永久代依然存在,用于存储类元数据和其他信息,但常量池不再存放在永久代中。
  • JDK 8 及之后:
    方法区被移除,取而代之的是元空间(Metaspace)。
    元空间使用本地内存存储类元数据(如类名、方法、字段等),不再受限于堆大小。
    运行时常量池依然位于堆中,不在元空间内。

3、常量池和运行时常量池的区别

常量池和运行时常量池是 Java 中两个相关但不同的概念,它们分别用于不同的阶段和存储不同类型的数据。

1)常量池(Constant Pool)
常量池是在编译期生成的,是 Class 文件的一部分。每个 Class 文件都包含一个常量池,存储了编译期间生成的各种字面量和符号引用。

特点和存储内容

  • 位置:Class 文件中。
  • 存储内容:
    字面量(如整数、浮点数、字符串常量)。
    符号引用(如类名、方法名、字段名、接口方法名)。
    作用:用于支持 Java 虚拟机在类加载时和运行时对这些字面量和符号引用的解析。

2)运行时常量池(Runtime Constant Pool)
运行时常量池是从常量池加载而来的,是每个类或接口在加载后存储在 JVM 内存中的一部分。运行时常量池存在于方法区中(在 JDK 8 之后,方法区被元空间取代,但运行时常量池仍然位于堆内存中)。

特点和存储内容

  • 位置:方法区的一部分(JDK 8 之后为堆内存)。
  • 存储内容:
    从 Class 文件的常量池中加载的字面量和符号引用。
    动态生成的常量(如字符串池中的字符串常量)。
  • 作用:在运行时为 JVM 提供字面量和符号引用的解析与存储支持,允许在运行时添加新的常量。

主要区别:生成时机、位置、内容、作用不同

4、内存溢出和内存泄漏

内存溢出(OutOfMemory)和内存泄漏(Memory Leak)是两种常见的内存管理问题,它们在性质、原因和影响方面有所不同。

1)内存溢出
定义:内存溢出是指程序在运行过程中,申请内存时没有足够的内存可用,导致 JVM 或操作系统抛出内存不足的错误。

原因

  • 堆内存溢出:程序创建了太多对象,导致堆内存耗尽。例如,使用了一个大集合而没有适时清除无用对象。
  • 方法区溢出:加载了过多的类或方法,导致方法区(元空间)耗尽。这在频繁动态生成类的应用(如使用大量代理或反射)中常见。
  • 栈内存溢出:递归调用过深或方法调用栈过大,导致栈内存耗尽。例如,递归没有适时结束。

表现

  • 堆内存溢出:JVM 抛出 java.lang.OutOfMemoryError: Java heap space 错误。
  • 方法区溢出:JVM 抛出 java.lang.OutOfMemoryError: Metaspace(JDK 8 及以后)或 java.lang.OutOfMemoryError: PermGen space(JDK 7 及以前)错误。
  • 栈内存溢出:JVM 抛出 java.lang.StackOverflowError 或 java.lang.OutOfMemoryError: unable to create new native thread 错误。

解决方法

  • 优化代码:避免创建过多的对象,使用更有效的数据结构。
  • 调整 JVM 参数:增加堆内存(-Xmx),增加元空间大小(-XX:MaxMetaspaceSize)。
  • 改进算法:减少递归深度,使用循环替代深度递归。

2)内存泄漏
定义:内存泄漏是指程序在运行过程中,已经不再使用的对象或资源仍然被引用,导致这些对象或资源无法被垃圾收集器回收,逐渐耗尽内存。

原因

  • 长生命周期对象引用短生命周期对象:如静态集合类持有对动态创建对象的引用,导致动态对象不能被回收。
  • 未正确关闭资源:如数据库连接、文件流未关闭。
  • 事件监听和回调:注册的事件监听器或回调未被适时移除,导致对象无法被回收。

表现

  • 内存使用持续增加:应用程序在运行过程中,内存使用持续增加,直至耗尽内存。
  • 性能下降:随着内存使用增加,GC 的频率和时间增加,导致性能下降。

解决方法

  • 检查引用:确保不再使用的对象不再被引用。
  • 及时关闭资源:使用 try-with-resources 语句或在 finally 块中关闭资源。
  • 移除监听器:在不再需要时,移除注册的事件监听器或回调。

总结
内存溢出 vs 内存泄漏

5、Java 对象大小计算

计算 Java 对象的大小涉及对象头、实例数据和对齐填充。以下是具体的计算方法:

1)对象头(Object Header):

  • Mark Word:32 位 JVM 中占 4 字节,64 位 JVM 中占 8 字节。
  • Class Pointer:32 位 JVM 中占 4 字节,64 位 JVM 中占 8 字节(使用压缩指针时为 4 字节)。

2)实例数据(Instance Data):

  • 对象的字段数据。基本类型字段的大小如:int 4 字节,byte 1 字节。引用类型字段在 32 位 JVM 中占 4 字节,64 位 JVM 中占 8 字节(使用压缩指针时为 4 字节)。

3)对齐填充(Padding):

  • 为满足对象大小是 8 字节的倍数,JVM 可能会在对象结尾添加填充字节。

示例:

public class ComplexObject {
    int intField;         // 4 字节
    double doubleField;   // 8 字节
    Object refField;      // 4 字节(压缩指针)
    byte byteField;       // 1 字节
}

计算步骤:

  • 对象头:64 位 JVM 使用压缩指针时为 16 字节(8 字节 Mark Word + 8 字节 Class Pointer)。
  • 实例数据:intField 4 字节,doubleField 8 字节,refField 4 字节,byteField 1 字节。
  • 对齐填充:当前大小为 16 + 4 + 8 + 4 + 1 = 33 字节,需填充 7 字节。
    总大小:16 + 4 + 8 + 4 + 1 + 7 = 40 字节。

⭐️总结

  • 对象头:64 位 JVM 压缩指针时为 16 字节。
  • 实例数据:基本类型按大小分配,引用类型使用压缩指针为 4 字节。
  • 对齐填充:确保总大小为 8 字节的倍数。

6、GCROOT都有什么

在 Java 中,GCROOT(垃圾回收根)是指可以直接或间接引用到活动对象的引用链的起点。GC ROOT 对象是 GC 不会回收的对象,因为它们在程序执行期间仍然可访问。

GC ROOT 可能包括以下几种类型的对象:

静态变量(Static Variables):类的静态变量引用的对象。
本地变量(Local Variables):当前活动线程的栈帧中的局部变量引用的对象。
活动线程(Active Threads):尚未终止的线程引用的对象。
JNI 引用(JNI References):由本地方法(Native Method)引用的 Java 对象。
虚拟机内部引用(JVM Internal References):由虚拟机自身引用的对象,如常量池、类的引用等。

7、常用的JVM启动参数有哪些

JVM (Java虚拟机)的启动参数用于配置和调整Java应用程序的运行时行为。以下是一些常用的JVM启动参数:

  • .-Xmx: 指定Java堆内存的最大限制。例如,-Xmx512m 表示最大堆内存为512兆字节
  • -Xms: 指定Java堆内存的初始大小。例如,-Xms256m 表示初始堆内存为256兆字节
  • -Xss: 指定每个线程的堆栈大小。例如,-Xss256k 表示每个线程的堆栈大小为256千字节。
  • -XX:MaxPermSize (对于Java 7及之前的版本)或-XX:MaxMetaspaceSize(对于Java 8及以后的版本): 指定永久代 ava 7及之前)或元空间 (Java8及以后) 的最大大小。
  • -XX:PermSize(对于Java 7及之前的版本)或 -XXMetaspaceSize (对于Java 8及以后的版本): 指定永久代 Java 7及之前)或元空间 (Java 8及以后) 的初始大小。
  • -Xmn: 指定年轻代的大小。例如,-Xmn256m 表示年轻代大小为256兆字节,
  • -XX:SurivorRatio: 指定年轻代中Eden区与Survivor区的大小此例。例如-XX:SuvivorRatio=8 表示Eden区与每个Surivor区的大小比例为8:1.
  • -XX:NewRatio: 指定年轻代与老年代的大小比例。例如,-XX:NewRatio=2 表示年轻代和老年代的比例为1:2.
  • -XX:MaxGCPauseMilis: 设置垃圾回收的最大暂停时间目标。例如,-XX:MaxGCPauseMilis=100 表示垃圾回收的最大暂信时间目标为100毫秒
  • -XX:ParallelGCThreads: 指定并行垃圾回收线程的数量。例如,-XX:ParallelGCThreads=4 表示使用4个线程进行并行垃圾回收,
  • -XX:+UseConcMarkSweepGC: 启用并发标记清除垃圾回收器。
  • -XX:+UseG1GC: 启用G1 (Garbage First) 垃圾回收器。
  • -Dproperty=value: 设置Java系统属性,可以在应用程序中使用 System.getProperty"property")来获取这些属性的值。这些是一些常见的JM启动参数,可以根据应用程序的需和性能调优的目标进行调整。JVM启动参数的使用可以显著影响应用程序的性能和行为,因此在设置这些参数时需要谨慎。同时,JVM支持的启动参数因不同的JVM版本和供应商而有所不同,建议查阅相关文档以获取更详细的信息。

8、TLAB

Thread Local AllocationBuffer,线程本地分配缓冲区。

1)原理:
在多线程并发情况下,对象的分配会存在竞争,多个线程同时申请内存可能会导致频繁的加锁和解锁操作,从而降低分配效率。TLAB 的出现就是为了解决这个问题。

TLAB 为每个线程分配了一块独立的内存区域,每个线程在自己的 TLAB 区域内进行对象的分配,不再涉及到全局的内存分配锁,从而避免了多线程之间的竞争。

2)TLAB 的优点包括:

  • 降低内存分配竞争:每个线程有自己的 TLAB,避免了多线程之间的内存分配竞争,提高了分配效率。
  • 减少同步开销:减少了因对象分配而引起的同步开销,提高了多线程并发时的性能。
  • 提高缓存局部性:TLAB 中的对象是连续分配的,有利于提高 CPU 缓存的命中率。

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

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

相关文章

ROS学习记录:栅格地图格式

一、机器人导航所使用的地图数据,就是ROS导航软件包里的map_server节点在话题 /map 中发布的消息数据,消息类型是nav_msgs消息包中的OccupancyGrid,它的中文意思的占据栅格,是一种正方形小格子组成的地图。 二、对障碍物进行俯视&…

单片机+TN901非接触式红外测温设计

摘要 温度测量技术应用十分广泛,而且在现代设备故障检测领域中也是一项非常重要的技术。但在某些应用领域中,要求测量温度用的传感器不能与被测物体相接触,这就需要一种非接触的测温方式来满足上述测温需求。本论文正是应上述实际需求而设计的…

搭建python虚拟环境,并在VSCode中使用

创建环境 python -m venv E:\python\flask\venv激活环境 运行下图所示的bat文件 退出环境 执行下面的语句 deactivateVSCode中配置: ①使用CTRLshiftp命令,使用CTRLshiftp命令,输入: Python: Select Interpreter②选择之前创建…

C++ 11 【线程库】【包装器】

💓博主CSDN主页:麻辣韭菜💓   ⏩专栏分类:C修炼之路⏪   🚚代码仓库:C高阶🚚   🌹关注我🫵带你学习更多C知识   🔝🔝 目录 前言 一、thread类的简单介绍 get_id…

IO进程线程(七)代码替换函数、守护进程

文章目录 一、代码替换函数(一)system函数(二)exec函数族 二、守护进程(一)创建1. 脱离父进程影响2. 脱离原会话组和进程组的影响3.修改进程工作目录4. 修改进程创建文件的掩码5. 关闭从父进程继承的文件描…

轻松搞定阿里云域名DNS解析

本文将会讲解如何设置阿里云域名DNS解析。在进行解析设置之前,你需要提前准备好需要设置的云服务器IP地址、域名以及CNAME记录。 如果你还没有云服务器和域名,可以参考下面的方法注册一个。 申请域名:《Namesilo域名注册》注册云服务器&…

[Cloud Networking] Layer Protocol (continue)

文章目录 1. STP / RSTP / MSTP Protocol1.1 STP的作用1.2 STP 生成树算法的三个步骤1.3 STP缺点 2. ARP Protocol3. DHCP Protocol3.1 DHCP 三种分配方式3.2 DHCP 攻击 4. IPSEC / MACSEC 1. STP / RSTP / MSTP Protocol 1.1 STP的作用 消除二层环路:通过阻断冗余…

大模型,也在卷价格

“百模大战”已从算力战、规模战蔓延到了价格战。 5月15日,字节跳动宣布豆包主力模型(小于等于32K)在企业市场的定价只有0.0008元/千Tokens,0.8厘就能处理1500多个汉字,比行业便宜99.3%;5月21日&#xff0…

【乐吾乐3D可视化组态编辑器】用开关控制巡检车和路灯

一、运动设备开关控制 3D组态编辑器地址:3D可视化组态 - 乐吾乐Le5le 1.在场景中新建模拟运动设备及控制面板:启动/停止 2.单击巡检车设备新建模拟动画 3.设置模拟动画属性 4.单击启动面板,新建交互事件 5.设置交互触发类型,新建…

WinForms 应用(.NET 8.0)使用ReportViewerCore.WinForms显示打印RDLC报表

在要WinForms 应用(.NET 8.0)中,显示RDLC报表,就要使用ReportViewerCore.WinForms。原来的ReportViewer只能在.NET Framework框架下运行。 1.ReportViewerCore.WinForms 程序包说明 SQL Server Reporting Services ReportViewer…

使用CodeGen进行程序综合推理

Program Synthesis with CodeGen — ROCm Blogs (amd.com) CodeGen是基于标准Transformer的自回归语言模型家族,用于程序合成,正如作者所定义的,它是一种利用输入-输出示例或自然语言描述生成解决指定问题的计算机程序的方法。 我们将测试的…

Mysql使用中的性能优化——单次插入和批量插入的性能差异

一般Mysql的客户端和服务端不在一台机器上,所以它们之间的通信需要通过网络进行。我们本次实验,希望抛开网络的影响,测试不同SQL方案在Mysql服务器上的执行效率的对比。于是我们使用“存储过程”来辅助测试。 结论 先上结论: 批…

HTML静态网页成品作业(HTML+CSS)—— 家乡南宁介绍网页(2个页面)

🎉不定期分享源码,关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 🏷️本套采用HTMLCSS,未使用Javacsript代码,共有2个页面。 二、作品演示 三、代…

Git+Gitlab 远程库测试学习

Git远程仓库 1、Git远程仓库 何搭建Git远程仓库呢?我们可以借助互联网上提供的一些代码托管服务来实现 Gitee 码云是国内的一个代码托管平台,由于服务器在国内,所以相比于GitHub,码云速度会更快 码云 Gitee - 基于 Git 的代码托…

每日一题——Python实现PAT乙级1037 在霍格沃茨找零钱(举一反三+思想解读+逐步优化)

一个认为一切根源都是“自己不够强”的INTJ 个人主页:用哲学编程-CSDN博客专栏:每日一题——举一反三Python编程学习Python内置函数 Python-3.12.0文档解读 目录 我的写法 时间复杂度分析: 空间复杂度分析: 我要更强 哲学…

vivado DIAGRAM、HW_AXI

图表 描述 块设计(.bd)是在IP中创建的互连IP核的复杂系统 Vivado设计套件的集成商。Vivado IP集成器可让您创建复杂的 通过实例化和互连Vivado IP目录中的IP进行系统设计。一块 设计是一种分层设计,可以写入磁盘上的文件(.bd&…

搭建多平台比价软件你必须知道的几大知识板块

为了搭建一个多平台比价系统并使其发挥作用,你需要考虑以下几个关键的平台支持方面: 数据API采集平台: 电商平台:如亚马逊、淘宝、京东等,这些平台提供了丰富的商品信息和价格数据。旅行服务平台:如携程、…

Vue基础知识:插槽——默认插槽,插槽的后备内容,具名插槽,作用域插槽的认识与使用。(slot,#default,row的认识)

1.插槽的基本认识: 作用:让组件内部的一些结构支持自定义 插槽的分类: 1.默认插槽(组件内只能定制一处结构) 2.具名插槽(组件内可以定制多次结构) 简单而言:就是你希望封装一个…

探索教研在线平台的系统架构

教研在线平台作为一家致力于教育技术领域的企业,其系统架构扮演着至关重要的角色。本文将深入探讨教研在线平台的系统架构,从技术架构、数据架构和安全架构等方面进行分析,以期帮助读者更好地理解这一教育科技平台的运作模式。 技术架构是教研…

【Ardiuno】使用ESP32网络功能调用接口数据(图文)

接着上文连通wifi后,我们通过使用HTTPClient库进行网络相关操作,这里我们通过http协议进行接口调用。 为了简化操作,这里使用了本地服务器上的文件作为接口,正常操作时会调用接口后,将服务器返回的数据进行解析&#…