八股文——JVM

 1. JVM组成

1.1 JVM由哪些部分组成?运行流程?

  • Java Virtual Machine:Java 虚拟机,Java程序的运行环境(java二进制字节码的运行环境)
  • 好处:一次编写,到处运行;自动内存管理,垃圾回收机制
  • 程序运行之前,需要先通过编译器将 Java 源代码文件编译成 Java 字节码文件;
  • 程序运行时,JVM 会对字节码文件进行逐行解释,翻译成机器码指令,并交给对应的操作系统去执行。

 

 

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

  • JVM  <---> 操作系统(windows、linux)<---> 计算机硬件(cpu、内存条)
    java跨平台是因JVM屏蔽了操作系统的差异,真正运行代码的不是操作系统

 

 

  • JVM 主要由四个部分组成: 运行流程:
  • Java 编译器(javac)将 Java 代码转换为字节码(.class 文件)
  • 1. 类加载器(ClassLoader)
  • 负责加载 .class 文件,将 Java 字节码加载到内存中,并交给 JVM 执行
  • 2. 运行时数据区(Runtime Data Area)
  • 管理JVM使用的内存。主要包括:
  • 方法区(Method Area):存储类的元数据、常量、静态变量等。
  • 堆(Heap):存储所有对象和数组,垃圾回收器主要回收堆中的对象。
  • 栈(Stack):每个线程都有一个栈,用于存储局部变量、方法调用等信息。
  • 程序计数器(PC Register):每个线程有一个程序计数器,指示当前线程正在执行的字节码指令地址。
  • 本地方法栈(Native Method Stack):支持本地方法的调用(通过 JNI)。
  • 其中方法区和堆是线程共享的,虚拟机栈、本地方法栈和程序计数器是线程私有的。
  • 3. 执行引擎(Execution Engine)
  • 负责执行字节码,包含:
  • 解释器:逐条解释执行字节码。
  • JIT 编译器:将热点代码编译为机器码,提高执行效率。
  • 垃圾回收器:回收堆中的不再使用的对象,释放内存。
  • 4. 本地库接口(Native Method Library)
  • 允许 Java 程序通过 java本地接口JNI(Java Native Interface)调用本地方法(如 C/C++ 编写的代码),与底层系统或硬件交互。

 1.2 什么是程序计数器

  • 程序计数器:线程私有的,每个线程一份,内部保存字节码的行号。用于记录正在执行的字节码指令的地址。
  • 每个线程都有自己的程序计数器,确保线程切换时能够继续执行未完成的任务。

1.3 你能给我详细的介绍java堆吗?

  • Java堆是 JVM 中用于存储所有对象和数组的内存区域。线程共享的区域。当堆中没有内存空间可分配给实例,也无法再扩展时,则抛出OutOfMemoryError异常。
  • 它被分为:
  • 年轻代(存储新创建的对象),被划分为三部分:
  • Eden区:大多数新对象的分配区域;
  • S0 和 S1(两个大小严格相同的Survivor区):Eden 空间经过 GC 后存活下来的对象会被移到其中一个 Survivor 区域;
  • 老年代:在经过几次垃圾收集后,任然存活于Survivor的对象将被移动到老年代区间。
  • 永久代:JDK 7 及之前,JVM 的方法区(也称永久代),保存的类信息、静态变量、常量、编译后的代码;
  • 元空间:JDK 8 及之后,永久代被 Metaspace(元空间)取代,移除了永久代,把数据存储到了本地内存的元空间中,且其大小不再受 JVM 堆的限制,防止内存溢出。

1.4 什么是虚拟机栈

Java Virtual machine Stacks (java 虚拟机栈)

  • 每个线程在 JVM 中私有的一块内存区域,称为虚拟机栈,先进后出,用于存储方法的局部变量和方法调用信息;
  • 每个栈由多个栈帧(frame)组成,当线程执行方法时,为该方法分配一个栈帧(Stack Frame);
  • 每个线程只能有一个活动栈帧,对应着当前正在执行的那个方法;

垃圾回收是否涉及栈内存?
  • 垃圾回收主要指就是堆内存
  • 栈内存中不会有垃圾回收的概念,因为栈内存是由 JVM 自动管理的,方法执行完成时,栈帧弹栈,内存就会释放;
栈内存分配越大越好吗?
  • 未必,默认的栈内存通常为1024k;
  • 栈内存过大会导致线程数变少,例如,机器总内存为512m,目前能活动的线程数则为512个,如果把栈内存改为2048k,那么能活动的线程数减半;

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

  • 方法内的局部变量 本身是线程安全的,因为它们存储在每个线程独立的栈中,不会被其他线程共享。
  • 但如果局部变量是引用类型,并且该引用指向的对象逃离了方法作用范围(例如被返回或传递到外部),则需要考虑该对象的线程安全性。
  • 如果对象是可变的,并且被多个线程访问,可能会引发线程安全问题。
栈内存溢出情况(StackOverflowError)
  • 栈帧过多导致栈内存溢出;
    典型问题:递归调用会在栈中创建新的栈帧,如果递归深度过大,可能会导致栈空间耗尽,从而抛出

  • 栈帧过大导致栈内存溢出

堆栈的区别是什么?

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

1.5 说一下JVM运行时数据区

JVM 运行时数据区包括方法区、堆、栈、程序计数器和本地方法栈。

  • 方法区存储类的元数据、常量池、静态变量和 JIT 编译后的代码。
  • 类的结构信息:每个类的信息,如类名、父类名、接口、方法、字段的名称和描述等。常量池:存储常量值,如字符串常量、类常量等。静态变量:属于类的变量,而不是某个实例的变量。JIT编译后的代码是指 Jvm在运行时将热点代码从字节码编译为本地机器代码。方法区在 JDK 7 之前被称为 "永久代",从 JDK 8 开始,永久代被移除,改为使用元空间
  • 堆是 JVM 中最大的内存区域,负责存储所有的对象实例和数组,并进行垃圾回收。
  • 栈存储每个线程的局部变量、方法调用信息和返回地址等。
  • 堆和栈是线程共享和线程私有的区域。
  • 程序计数器是每个线程私有的,用于存储当前线程正在执行的字节码指令的地址。
  • 本地方法栈支持 JNI 本地方法调用,线程私有。
  • 专门为本地方法调用而设计。它用于执行本地代码时所需的栈空间。

1.6  能不能介绍一下方法区

  • 方法区 是 JVM 运行时数据区的一部分,主要用于存储类的信息、常量、静态变量以及 JIT 编译后的代码。
  • 在 JDK 7 之前,这部分内存称为永久代(PermGen),而在 JDK 8 以后,永久代被移除,取而代之的是元空间(Metaspace),它位于本地内存中,不再受堆内存限制。
  • 虚拟机启动的时候创建,关闭虚拟机时释放。
  • 方法区的内存由 JVM 管理,并在类卸载时进行垃圾回收。
  • 如果方法区域中的内存无法满足分配请求,则会抛出OutOfMemoryError: Metaspac

1.7 介绍一下运行时常量池?

常量池
  • 可以看作是一张表,虚拟机指令根据这张常量表找到要执行的类名、方法名、参数类型、字面量等信息

运行时常量池
  • 常量池是 .class 文件中的,当该类被加载,它的常量池信息就会放入运行时常量池,并把里面的符号地址变为真实地址

1.8 你听过直接内存吗?

  • 它不受 JVM 内存回收管理,是虚拟机的系统内存;
  • 常见于在 NIO 中使用直接内存,不需要在堆中开辟空间进行数据的拷贝,jvm可以直接操作直接内存,从而使数据读写传输更快。但分配回收成本较高。
  • 使用传统的IO的时间要比NIO操作的时间长了很多,也就说NIO的读性能更好。
  • 这个是跟我们的JVM的直接内存是有一定关系,如下图,传统阻塞IO的数据传输流程和NIO传输数据的流程。

2. 类加载器

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

  • JVM只会运行二进制文件,而类加载器(ClassLoader)的主要作用就是将.class字节码文件加载到JVM内存,生成对应的Class对象,供程序使用。

  • 启动类加载器(BootStrap ClassLoader):
  • 该类并不继承ClassLoader类,其是由C++编写实现。用于加载JAVA_HOME/jre/lib目录下的类库。
  • 扩展类加载器(ExtClassLoader):
  • 该类是ClassLoader的子类,主要加载JAVA_HOME/jre/lib/ext目录中的类库。
  • 应用类加载器(AppClassLoader):
  • 该类是ClassLoader的子类,主要用于加载classPath下的类,也就是加载开发者自己编写的Java类。
  • 自定义类加载器:
  • 开发者自定义类继承ClassLoader,实现自定义类加载规则。

类加载器的体系并不是“继承”体系,而是委派体系,类加载器首先会到自己的parent中查找类或者资源,如果找不到才会到自己本地查找。类加载器的委托行为动机是为了避免相同的类被加载多次

2.2 什么是双亲委派模型?

  • 双亲委派模型要求类加载器在加载某一个类时,先委托父加载器尝试加载。
  • 如果父加载器可以完成类加载任务,就返回成功;
  • 只有父加载器无法加载时,子加载器才会加载。

2.3 JVM为什么采用双亲委派机制?

  • 避免类的重复加载:父加载器加载的类,子加载器无需重复加载。

  • 保证核心类库的安全性:为了安全,保证类库API不会被修改。如 java.lang包下的类只能由 启动类加载器Bootstrap ClassLoader 加载,防止被篡改。

2.4 说一下类的生命周期

  • 一个类从被加载到虚拟机内存中开始,到从内存中卸载,它的整个生命周期包括了:
    加载、验证、准备、解析、初始化、使用和卸载这7个阶段。
  • 其中,验证、准备和解析这三个部分统称为连接(linking)。

2.5 说一下类装载的执行过程?

类装载过程包括三个阶段:载入、连接和初始化,连接细分为 验证、准备、解析,这是标准的 JVM 类装载流程。

  1. 加载(Loading):通过类加载器找到 .class 文件读取到内存,生成 Class 对象。
  2. 连接(Linking):

验证:检查字节码是否合法,防止恶意代码破坏 JVM;
准备:为类的静态变量分配内存并设置默认初始值,但不执行赋值逻辑;
解析:将常量池中的 符号引用(如类名、方法名)转为 直接引用(内存地址)。

  1. 初始化(Initialization):执行类的静态代码块和静态变量赋值。

在准备阶段,静态变量已经被赋过默认初始值了,在初始化阶段,静态变量将被赋值为代码期望赋的值。比如说 static int a = 1;,在准备阶段,a 的值为 0,在初始化阶段,a 的值为 1

类装载完成后的阶段:加载完成后,类进入‘使用阶段’。当 Class 对象不再被引用时,可能触发‘卸载’。

  • 使用:JVM 通过 Class 对象创建实例、调用方法,进入正常运行阶段。
  • 卸载:当 Class 对象不再被引用时,由 GC 回收,但 JVM 核心类(如 java.lang.*)不会被卸载。

3. 垃圾回收

3.1 简述java垃圾回收机制?(GC是什么?为什么要GC)

  • GC(Garbage Collection,垃圾回收)是 Java 中自动管理内存的机制,负责回收不再使用的对象,以释放内存空间。
  • 垃圾回收是 Java 程序员不需要显式管理内存的一大优势,它由 JVM 自动进行。

GC 的主要目的是:
自动管理内存:程序运行过程中会创建大量的对象,但一些对象在使用完后不再被引用。手动管理这些对象的内存释放非常繁琐且容易出错;
防止内存泄漏:如果不及时释放无用对象的内存,系统的可用内存会越来越少,最终可能导致 OutOfMemoryError;
避免内存溢出:GC 机制能够保证内存不会因为长期积累未回收的对象而耗尽。

3.2 对象什么时候可以被垃圾器回收?

  • 如果一个或多个对象没有任何的引用指向它了,那么这个对象现在就是垃圾,如果定位了垃圾,则有可能会被垃圾回收器回收。

如果要定位什么是垃圾,有两种方式来确定,
1. 引用计数法:通过计数引用的数量,当引用为 0 时回收。但不能处理循环引用
这种方法通过给每个对象维护一个引用计数器。当有一个新的引用指向该对象时,引用计数加 1;当引用离开时,计数减 1。
2. 可达性分析算法:通过检查对象是否从根对象可达,无法访问的对象可以回收。是 Java 使用的主要方法。
根对象是那些肯定不能当做垃圾回收的对象,就可以当做根对象
根对象包含:虚拟机栈中的局部变量;静态变量;活动线程的引用;JNI 引用的对象。

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

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

相关文章

在Pnetlab6上绕过TPM、安全启动和 RAM 检查安装windows 11笔记

笔者本次安装的windows11的镜像为: zh-cn_windows_11_enterprise_ltsc_2024_x64_dvd_cff9cd2d.iso 1、创建镜像目录并上传iso文件 mkdir /opt/unetlab/addons/qemu/win-win11x64-2024-LTSC //目录名称务必按照官方文档格式,否则无法识别 目录创建完成后,将.iso格式镜像上…

PCL点云库入门(第18讲)——PCL库点云特征之3DSC特征描述3D shape context descriptor

一、3DSC&#xff08;3D Shape Context&#xff09;特征算法原理 1. 背景 3DSC 是一种描述三维点云局部形状的特征描述子&#xff0c;受二维 Shape Context 的启发。它用于捕捉点云某一点局部的几何分布信息&#xff0c;对点云配准、识别等任务非常有效。 2. 基本思想 3DSC…

SpringBoot+Mysql校园跑腿服务平台系统源码

&#x1f497;博主介绍&#x1f497;&#xff1a;✌在职Java研发工程师、专注于程序设计、源码分享、技术交流、专注于Java技术领域和毕业设计✌ 温馨提示&#xff1a;文末有 CSDN 平台官方提供的老师 Wechat / QQ 名片 :) Java精品实战案例《700套》 2025最新毕业设计选题推荐…

分库分表的取舍

文章目录 大数据量下采用**水平分表**的缺点**1. 跨表查询复杂性与性能下降****2. 数据分布不均衡****3. 分布式事务与一致性问题****4. 扩展性受限****5. 查询条件限制与索引管理复杂****6. 数据迁移与维护成本高****7. 业务逻辑复杂度增加****总结** shardingJdbc分片策略**1…

Vue3解决“找不到模块@/components/xxx.vue或其相应的类型声明ts文件(2307)”

问题 1&#xff1a;如果没有这个env.d.ts文件&#xff0c;就新建 declare module "*.vue" {import { DefineComponent } from "vue";const component: DefineComponent<{}, {}, any>;export default component; }2&#xff1a;如果有tsconfig.json文…

计算机视觉与深度学习 | 基于MATLAB的图像特征提取与匹配算法总结

基于MATLAB的图像特征提取与匹配算法全面指南 图像特征提取与匹配 基于MATLAB的图像特征提取与匹配算法全面指南一、图像特征提取基础特征类型分类二、点特征提取算法1. Harris角点检测2. SIFT (尺度不变特征变换)3. SURF (加速鲁棒特征)4. FAST角点检测5. ORB (Oriented FAST …

如何通过API接口获取淘宝商品列表?操作详解

一、准备工作 注册开发者账号 访问淘宝开放平台官网/万邦开放平台&#xff0c;完成企业开发者认证&#xff08;个人账号权限受限&#xff09;&#xff0c;使用已有淘宝账号可直接登录。创建应用并填写基本信息&#xff08;如应用名称、类型等&#xff09;&#xff0c;系统生成A…

大数据驱动企业决策智能化的路径与实践

&#x1f4dd;个人主页&#x1f339;&#xff1a;慌ZHANG-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 一、引言&#xff1a;数据驱动的企业竞争力重构 在这个瞬息万变的商业时代&#xff0c;“快者胜”的竞争逻辑愈发明显。企业如何在复杂环…

DataGridView关闭默认第一列及表头居中设置

1、关闭默认第一列 如上图所示&#xff0c;C#和VB.net中的DataGridView控件都是有一个默认的第一列&#xff08;虽然是空白&#xff09;的&#xff0c;如何关闭这个默认列呢&#xff1f; 把“RowHeadersVisible”的值设置成“false”就可以了&#xff1a; 2、表头居中显示 如上…

nodejs express 打包部署

当前文件路径 webpack.config.js const path require(path); module.exports {entry: ./app.js, // Express 入口文件target: node, // 指定 Node.js 环境output: {path: path.resolve(__dirname, dist),filename: bundle.js},mode: production };打包命令 npx webpac…

CentOS 7 修改为静态 IP 地址完整指南

在企业网络环境中,服务器通常需要配置静态 IP 地址以确保网络连接的稳定性和可管理性。以下是使用 NetworkManager 工具在 CentOS 7 系统中将动态 IP 配置修改为静态 IP 的完整指南: 一、检查当前网络配置 查看网络连接状态: 使用 nmcli connection show 命令列出所有网络连…

微信小程序动态组件加载的应用场景与实现方式

动态组件加载的应用场景与实现方式 你提供的代码展示了微信小程序中动态加载组件的方法&#xff0c;但这种方式在实际开发中需要注意使用场景和实现细节。下面我来详细说明如何应用&#xff1a; 应用场景 按需加载组件&#xff1a;在某些条件满足时才加载组件动态配置组件&a…

学习记录: 使用react-router-dom

假设有一个vite创建的react项目,先npm install react-router-dom. 在app中: import { RouterProvider, createBrowserRouter } from "react-router-dom"; import Login from "./comm/Login"; import Home from "./comm/Home"; import TotalMan…

Angular中Webpack与ngx-build-plus 浅学

Webpack 在 Angular 中的概念 Webpack 是一个模块打包工具&#xff0c;用于将多个模块和资源打包成一个或多个文件。在 Angular 项目中&#xff0c;Webpack 负责将 TypeScript、HTML、CSS 等文件打包成浏览器可以理解的 JavaScript 文件。Angular CLI 默认使用 Webpack 进行项目…

java中word快速转pdf

java中word快速转pdf 网上其他方法转pdf要不转的太慢&#xff0c;要不就是损失格式&#xff0c;故而留下此方法留作备用。 文章目录 java中word快速转pdf一、依赖二、依赖包三、代码 一、依赖 <dependency><groupId>com.aspose</groupId><artifactId>…

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…

Unity使用代码分析Roslyn Analyzers

一、创建项目&#xff08;注意这里不要选netstandard2.1会有报错&#xff09; 二、NuGet上安装Microsoft.CodeAnalysis.CSharp 三、实现[Partial]特性标注的类&#xff0c;结构体&#xff0c;record必须要partial关键字修饰 需要继承DiagnosticAnalyzer 注意一定要加特性Diagn…

knife4j:4.3.0 default-flat-param-object: true 没有生效

Get 方式请求 前端接口文档中的键值对方式&#xff08;get&#xff09;发送对象参数&#xff0c;将对象请求参数展开

C++.OpenGL (15/64)Assimp(Open Asset Import Library)

Assimp(Open Asset Import Library) 3D模型加载核心流程 #mermaid-svg-cKmTZDxPpROr7ly1 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-cKmTZDxPpROr7ly1 .error-icon{fill:#552222;}#mermaid-svg-cKmTZDxPpROr…

课堂笔记:吴恩达的AI课(AI FOR EVERYONE)-第一周part2 人工智能术语人工智能公司应该怎么做

人工智能术语&人工智能公司应该怎么做 一、人工智能术语 1.机器学习&#xff1a; 让电脑能够不用开发软件&#xff0c;而自主获取某种能力的研究领域。 2.数据科学&#xff1a; 从数据中提取知识和见解的科学&#xff1b; 3.深度学习&#xff1a; 度学习是一种机器…