【Java】你真的了解JVM吗?

article/2025/7/16 16:38:53

类加载机制

JVM(Java虚拟机)中的类加载机制是指将Java类的字节码加载到内存中,并为其创建Class对象的过程。类加载机制的核心在于“类加载器”,它是负责加载类的组件。Java中的类加载机制主要包括以下几个步骤:

  1. 加载:查找并加载类的字节码文件(如 .class 文件),并在内存中生成一个Class对象。这个过程通常是通过类加载器来实现的。

  2. 链接

    • 验证:检查加载的类文件是否符合JVM的要求,以保证类的正确性和安全性。
    • 准备:为类的静态变量分配内存,并设置默认值。
    • 解析:将类中的符号引用转换为直接引用,比如将方法的名称解析为内存中的方法地址。
  3. 初始化:执行类的初始化代码,主要是执行静态初始化块和静态变量的赋值操作。

四个主要的类加载器:

  • 启动类加载器(Bootstrap ClassLoader):负责加载JVM的核心类库,通常来自 $ JAVA_HOME/lib目录下的类。
  • 扩展类加载器(Extension ClassLoader):加载JRE扩展目录(如  $ $JAVA_HOME/lib/ext)下的类。
  • 应用类加载器(Application ClassLoader):加载用户classpath下的类,是最常用的类加载器。
  • 自定义类加载器:用户可以通过继承ClassLoader类自定义加载器,加载特定的类或资源。

双亲委派模型

双亲委派模型是Java类加载机制中的一个重要原则,主要用于防止类的重复加载和确保Java的安全性。

具体规则如下:

  1. 当一个类加载器接收到类加载请求时,它首先会将请求委托给它的父类加载器(即上层的类加载器)进行尝试加载。
  2. 只有在父类加载器无法找到所需的类时,子加载器才会尝试自己加载这个类。

这种设计的好处包括:

  • 避免了类的重复加载。比如,如果有多个类加载器加载同一个类,由于父类委派机制,只有最顶层的加载器会加载类,避免了冲突。
  • 增强了安全性。基本的Java类库被顶层的启动类加载器加载,确保了这些关键类不会被任意的自定义类加载器替换。

在实际应用中,双亲委派模型能有效地维护类加载的顺序和层次结构,为Java的可移植性和安全性提供了保障。

JVM内存划分

Java虚拟机(JVM)的内存区域划分是理解Java程序执行过程的重要组成部分。JVM内存结构可分为几个主要区域,每个区域的用途和特性皆不同。以下是常见的JVM内存区域划分及其作用:

1. 程序计数器(Program Counter Register)

  • 作用:用于表示当前线程所执行的字节码的行号指示器。每个线程都有独立的程序计数器,线程切换时能够恢复到之前执行的位置。
  • 特点:它是线程私有的,内存占用较小。它的存在使得Java能够支持多线程。

2. Java虚拟机栈(Java Virtual Machine Stack)

  • 作用:用于存储局部变量、方法参数和返回值,以及方法调用的栈帧信息。每个线程都有自己的栈,栈帧在方法调用时创建,在方法执行完成后销毁。
  • 特点:局部变量的存储类型包括基本数据类型和对象引用。由于栈的大小是有限的,过多的递归调用可能导致StackOverflowError

3. 本地方法栈(Native Method Stack)

  • 作用:与Java虚拟机栈类似,但用于执行本地方法(Native Method)。而本地方法一般是使用C、C++等编写的代码。
  • 特点:每个线程都有自己独立的本地方法栈。

4. 堆(Heap)

  • 作用:用于存放对象实例和数组,是JVM中最大的一块内存区域。所有对象的默认存储区域,垃圾回收器集中管理这里的内存。
  • 特点:堆内存是共享的,所有线程都可以访问。对象的创建和销毁(通过垃圾回收)主要在堆中进行。由于堆的动态性,容易受到OutOfMemoryError异常。

5. 方法区(Method Area)/ 运行时常量池(Runtime Constant Pool)

  • 作用:用于存放类信息、常量、静态变量、字节码等数据。方法区也被称为非堆区。
  • 特点:存储类的结构信息以及类加载后生成的常量池内容。当类加载后,这些信息就被存储在方法区。它可以是共享的,并可能与堆一起进行垃圾回收。此区域可能会抛出OutOfMemoryError异常。

6. 运行时常量池(Runtime Constant Pool)

  • 作用:是方法区的一部分,存储编译器生成的各种字面量和符号引用。
  • 特点:例如,字符串常量和静态常量都会存储在这里。运行时常量池提供了动态的常量使用能力。

7. 直接内存(Direct Memory)

  • 作用:在Java中,可以通过ByteBuffer.allocateDirect()来分配直接内存,这部分内存不受JVM堆的限制,用于提高I/O性能。
  • 特点:直接内存不是由JVM自动管理的,需要手动管理。因此可能导致内存泄露。

总结

上述每个区域都有其独特的功能和特性,彼此之间又相互关联,共同支撑Java程序的运行。陆续的内存区域划分帮助程序员理解内存的动态分配、释放和管理,为更有效的内存使用、性能优化及故障排查提供了基础。

垃圾回收机制(GC) 

Java虚拟机(JVM)的垃圾回收(Garbage Collection, GC)机制是自动管理内存的关键部分。它的主要任务是识别和回收不再被引用的对象,以便释放内存并减少内存泄漏的风险。下面将详细介绍JVM的GC机制,包括如何找到垃圾对象以及如何回收垃圾对象。

如何找到垃圾

JVM上使用多种算法来识别不可达对象,常见的方法有:

  1. 引用计数法

    • 每个对象维护一个引用计数器,记录有多少个引用指向该对象。当引用被新增时计数器加一,引用失效时计数器减一。
    • 当计数器为零时,说明没有引用指向该对象,可以被回收。
    • 缺陷:无法处理循环引用的情况。
  2. 可达性分析(Reachability Analysis)

    • 是目前主流的GC算法。通过使用"根(Root)"对象作为起点,如线程栈、本地变量、常量等,进行图的遍历。
    • 从根对象开始,查找所有直接引用的对象,并继续查找这些对象引用的对象,直至遍历完所有可达对象。
    • 对于未被遍历到的对象,JVM判定其为垃圾,可以回收。

垃圾回收的方式

在确定了垃圾对象后,JVM的GC机制通常采用几种策略来回收这些对象:

  1. 标记-清除(Mark-Sweep)

    • 标记阶段:首先标记所有可达的对象。
    • 清除阶段:遍历堆,回收未标记的对象。
    • 优缺点:实现简单,但会产生内存碎片。
  2. 标记-整理(Mark-Compact)

    • 标记阶段:与标记-清除相同,标记所有可达对象。
    • 整理阶段:将存活的对象移动到堆的一端,更新对象的引用,消除内存碎片。
    • 优缺点:避免了内存碎片问题,但移动对象会带来额外开销。
  3. 复制算法(Copying)

    • 将内存分为两个相等的区域(半区),每次只使用一个区域。
    • 当进行GC时,将存活对象从当前区域复制到另一个区域,再清空当前区域。
    • 优缺点:简单高效,避免了内存碎片。但需要额外的内存空间。
  4. 分代收集(Generational Collection)

    • 将堆内存分为年轻代(Young Generation)、老年代(Old Generation)和永生代(Permanent Generation/Metaspace,具体实现和定义因JVM而异)。
    • 年轻代:大部分新创建的对象都是在此区域分配,GC频繁(Minor GC),回收速度快。
    • 老年代:存储经历多次GC仍然存活的对象,GC较少(Major GC或Full GC)。
    • 大多数对象只在年轻代存活的时间很短,因此采用频繁回收的策略可以提高效率。

垃圾回收的过程

  1. GC触发

    • 在内存不足或者JVM特定的条件下,触发GC。比如Heap内存使用达到一定阈值。
  2. 执行标记和清理

    • 通过上面所述的算法(如Mark-Sweep或Copying)执行GC工作,标记可达对象并清理不可达对象。
  3. 更新引用

    • 在移动对象或清理记忆时,更新对应引用。
  4. 执行Finalize(若适用):

    • 在对象被回收之前,调用对象的finalize()方法进行清理。

总结

JVM的垃圾回收机制是通过自动识别和回收不再使用的对象来管理内存的,减少了手动内存管理的复杂性。通过标记-清除、标记-整理、复制算法和分代收集等不同策略,JVM能够高效地管理堆内存,提升Java应用程序的性能。理解这些机制可以帮助开发者更好地优化代码和调试内存问题。


http://www.hkcw.cn/article/AvQKJOZvTb.shtml

相关文章

JVM学习-内存结构(二)

一、堆 1.定义 2.堆内存溢出问题 1.演示 -Xmx设置堆大小 3.堆内存的诊断 3.1介绍 1,2都是命令行工具(可直接在ideal运行时,在底下打开终端,输入命令) 1可以拿到Java进程的进程ID,2 jmap只能查询某一个时…

JVM相关内容

jvm的跨平台,字节码的作用 jvm的跨平台 不同操作系统系统运行的JVM不一样,但度能够处理对应的字节码文件 字节码的作用 利用编译节省了运行的时候的效率 JVM整体结构 类加载子系统:用于加载不同的class(字节码)文…

Sqlite3数据库表内数据批量读取操作---sqlite3_stmt机制

0、引言 在前面两篇文章已经对数据环境搭建、数据批量写入库中进行了较为详细的讲解。因此,基于前两篇文章内容的基础上,本文主要从数据库中批量数据读取操作进行梳理讲解。 嵌入式数据库SQLite 3配置使用详细笔记教程_sqlite3-CSDN博客 SQLite 3 优化批…

官方指定Jmeter配置JVM堆内存方式

软件测试资料领取:[内部资源] 想拿年薪40W的软件测试人员,这份资料必须领取~ 软件测试面试刷题工具领取:软件测试面试刷题【800道面试题答案免费刷】 1.概述 在使用Jmeter做性能测试过程中,可能会应为默认设置的堆内存值较小出…

线上JVM OOM问题,如何排查和解决?

今天咱们来聊聊让无数 Java 开发者头疼的 JVM OOM(Out Of Memory,内存溢出)问题。在面试中,OOM 问题也是面试官的“心头好”,因为它能直接考察你对 JVM 的理解,以及你在实际问题面前的排查和解决能力。 一…

JVM常见线上问题:CPU 100%、内存泄露问题排查

一、CPU 100% 问题排查 1.1、找到 cpu 占有率最高的 java 进程号 使用命令: top -c 显示运行中的进程列表信息, shift + p 使列表按 cpu 使用率排序显示。 PID = 2227 的进程,cpu 使用率最高 1.2、根据进程号找到 cpu 占有率最高的线程号 使用命令: top -Hp {pid} ,同…

JVM 一文详解

目录 JVM 简介 JVM 中的内存区域划分 1. 堆(一个进程只有一份 ------ 线程共享) 2. 栈(一个进程可以有 N 份 ------ 线程私有) Java 虚拟机栈: 本机方法栈: 3. 程序计数器(一个线程可以…

【JVM】关于JVM的内部原理你到底了解多少(八股文面经知识点)

前言 🌟🌟本期讲解关于HTTPS的重要的加密原理~~~ 🌈感兴趣的小伙伴看一看小编主页:GGBondlctrl-CSDN博客 🔥 你的点赞就是小编不断更新的最大动力 🎆那么废话不…

深入理解 JVM 的栈帧结构

🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/literature?__c=1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编程,高并发设计,Springboot和微服务,熟悉Linux,ESXI虚拟化以及云原生Docker和K8s…

JVM 机制

目录 一、什么是 JVM: 二、JVM 的运行流程: 三、JVM 内存区域划分: 1、( 1 ) 程序计数器: 1、( 2 ) 元数据区: 1、( 3 ) 栈: 1、( 4 ) 堆: 四、类加载: 1、什么时候会触…

【JVM】类加载机制

文章目录 类加载机制类加载过程1. 加载2. 验证3. 准备4. 解析偏移量符号引用和直接引用 5. 初始化 类加载机制 类加载指的是,Java 进程运行的时候,需要把 .class 文件从硬盘读取到内存,并进行一些列的校验解析的过程(程序要想执行…

【JVM】从零开始深度解析JVM

本篇博客给大家带来的是JVM的知识点, 重点在类加载和垃圾回收机制上. 🐎文章专栏: JavaEE初阶 🚀若有问题 评论区见 ❤ 欢迎大家点赞 评论 收藏 分享 如果你不知道分享给谁,那就分享给薯条. 你们的支持是我不断创作的动力 . 王子,公主请阅🚀 …

一篇文章带你解决笔试面试中的jvm问题

JVM内存区域划分 JVM启动的时候,会申请到一整个很大的内存区域.JVM是一个应用程序,要从操作系统里申请内存.JVM就根据需要,把空间分为几个部分,每个部分各自有不同的功能.具体划分如下: 分为:栈,堆,程序计数器,元数据区 Heap(堆):…

通义灵码2.5——基于编程智能体开发Wiki多功能搜索引擎

引言 在智能化浪潮重塑软件开发范式的今天,我借助开发一个基于编程智能体开发Wiki 多功能搜索引擎,深度体验了通义灵码2.5这一阿里云旗舰级AI编码助手,构建智能协作新范式。 该平台通过三大技术突破赋能开发全流程:基于编程智能…

基于SpringBoot的商家销售管理网站的设计与实现

湖南软件职业技术大学 本科毕业设计(论文) 设计(论文)题目 基于SpringBoot的商家销售管理网站的设计与实现 学生姓名 学生学号 所在学院 专业班级 校内指导教师 企业指导教师 毕业设计(论文)真实性承诺及声明 学生对毕业设计(论文)真实性承诺 本人郑重声明:所提交的毕…

各种噪声电流激励下电源PDN网络对系统时钟性能的影响

点击上面“蓝字”关注我们 电源分配是支持所有类型硅产品运行的基础设施的重要组成部分,但在设计过程中常被忽视。电源质量可能限制电路性能,并决定其工作可靠性。要真正解决电源分配问题,必须考虑包括芯片、封装和PCB在内的整个系统。 芯片…

【大模型】情绪对话模型项目研发

一、使用框架: Qwen大模型后端Open-webui前端实现使用LLamaFactory的STF微调数据集,vllm后端部署, 二、框架安装 下载千问大模型 安装魔塔社区库文件 pip install modelscope Download.py 内容 from modelscope import snapshot_downlo…

关于位图Bitmaps的介绍

目录 1、基本概念 1.1、介绍 1.2、关键字 1.3、结构原理 2、常用命令 2.1、SETBIT 2.2、GETBIT 2.3、BITCOUNT 2.4、BITOP 2.5、BITPOS 3、应用场景 4、使用示例 前言 Redis的Bitmaps是一种基于字符串的数据结构,用于处理位级别的操作。 Bitmaps在Redis…

【软件设计】通过软件设计提高 Flash 的擦写次数

目录 0. 个人简介 && 授权须知1. Flash 和 EEROM 基本情况2. 场景要求3. 软件设计思路4. 代码展示4.1 flash.h4.2 flash.c 0. 个人简介 && 授权须知 📋 个人简介 💖 作者简介:大家好,我是喜欢记录零碎知识点的菜鸟…

C 语言练习--初级

#学习C 代码, 做小练习时,自己运行代码竟然发现很多错误,记录一下。 1、计算器 根据输入的数值和符合,输出相应结果。 结果: #include "stdio.h"int Primary_math(int a, int b, char sign){int num0;swit…