当前位置: 首页 > news >正文

JVM理解(通俗易懂)

虽然网上有很多关于JVM的教程,但是都天花乱坠,很多都是一上来就JVM内存模型、JVM双亲委派等等,(可能我比较菜看不懂)。于是我自己决定写一篇能看懂的文章~如果有看不懂我就自己百度,大家有什么疑问也可以评论区交流~ 欢迎指点我的Error~

JVM概念

JVM大家都知道,就Java虚拟机嘛。但JVM名称的由来实际上是Java Virtual Machine 的缩写~
它是一台虚拟出来的计算机,能够运行在咱们平时所用的Window/Linux/Mac电脑上,也正因如此,Java能够实现跨平台性。
其次,Java虚拟机不与硬件直接交互,而是直接作用于操作系统。通过上面描述的操作系统能够帮我们完成与硬件的交互工作。大家可以看这张图:
在这里插入图片描述

JVM体系

我们平时所写的Java文件,我们都知道,它是会被编译器编译成二进制的.class后缀的文件。后续的执行流程,涉及几个非常重要的概念,我分小标题讲解一下。
溯石

类加载器(Class Loader)

JVM执行Java文件时,会通过类加载器加载对应的class文件到JVM中,此时正式进入JVM执行环节。

方法区(Method Area)

方法区主要存放元数据信息,如类信息、常量、静态变量、编译后到代码等。类加载器将class文件会先放入方法区。

堆区(Heap)

在Java内存架构中,堆内存(Heap)是对象实例的专属存储区域。垃圾收集器(Garbage Collector, GC)的核心使命便是扫描堆内存,识别并回收那些不再被引用的"垃圾对象",从而释放内存空间供新对象分配使用。

在JDK 1.8的里程碑式更新中,永久代(Permanent Generation, PermGen)这一传统方法区实现被彻底移除,取而代之的是元空间(Metaspace)。发展历程如下所示:

版本永久代变化
JDK6永久代用于存储类的元数据,包括类的名称、字段、方法、常量池等信息。永久代有固定大小限制,由-XX:MaxPermSize参数设置,当类加载过多时,容易出现java.lang.OutOfMemoryError: PermGen space错误。
JDK7永久代开始被元空间替代,元空间使用本地内存,允许更灵活的内存管理。虽然永久代仍然存在,但部分元数据已开始迁移到元空间。
JDK8永久代被完全移除,元空间成为存储类元数据的区域。元空间使用本地内存,不再受限于JVM堆内存,默认情况下会根据应用需要动态调整大小。元空间的大小可以通过-XX:MetaspaceSize和-XX:MaxMetaspaceSize等参数控制。

栈区(Stack)

栈区是我们代码的运行空间,栈区有虚拟机栈与本地方法栈。咱们编写的每一个方法都会在栈区执行,同时还保存了方法的局部变量、操作数栈和返回地址等信息。栈区属于线程独享区域~

本地方法栈(Native Method Stack)

我们查看Thread源码时,会惊奇的发现,源码几乎看不到什么实现,只有一个start0()方法,用native修饰且无方法体。它是由C来实现的,一般此类方法会被放入本地方法栈。
在这里插入图片描述

虚拟机栈
  • 异常说明
    当Java线程执行过程中,若其方法调用的栈帧深度超出了虚拟机栈预设的最大容量限制,系统将抛出StackOverflowError。这种错误常见于深度递归场景——每次递归调用都会在栈中新增一个栈帧,若递归终止条件缺失或栈容量不足,栈帧将持续累积直至突破栈深度阈值。
    现代JVM(如HotSpot)支持虚拟机栈的动态扩展机制。当线程执行需要更多栈空间时,JVM会尝试扩展栈的存储空间。然而,这种扩展并非无限制:若系统内存资源已耗尽,或扩展后的栈空间仍无法满足需求,JVM将抛出OutOfMemoryError。这种错误表明程序对内存的需求已超出当前系统可分配资源的极限,需通过优化内存使用或增加堆外存配置来解决。

  • 生命周期
    在Java内存体系中,栈(Stack)作为线程私有的内存区域,其内存管理机制具有独特特性。与堆(Heap)不同,栈不存在垃圾回收机制,因为栈帧的分配与回收遵循严格的LIFO(后进先出)原则。当方法执行完毕时,其对应的栈帧会自动弹出栈并释放内存,无需依赖垃圾回收器的介入。
    栈的生命周期与所属线程紧密绑定。当线程被创建时,JVM会为其分配独立的栈空间;当线程终止时,其栈内存也随之销毁,实现了资源的自动回收。这种设计保证了线程间栈内存的隔离性,避免了多线程环境下的内存冲突。

    在栈内存的分配层面,以下三类数据会在栈中占据空间:
    基本类型变量:包括byte、short、int、long、float、double、char、boolean这8种基本数据类型的局部变量。
    对象引用变量:存储对象在堆内存中的地址指针,而非对象本身。

相关文章:

  • Python内置函数---bin()
  • 11.thinkphp的模板
  • java将pdf转换成word
  • 3DGS之齐次坐标
  • 用户模块-SpringEvent观察者模式
  • ToB标杆!容联云入选量子位「2025中国AIGC应用报告」
  • CSS内边距、外边距、边框
  • 深入微服务核心:从架构设计到规模化
  • CSS初识
  • Android仿今日头条Kotlin版本
  • 机器学习算法-分类决策树
  • vue项目中使用tinymce富文本编辑器
  • CSS3 基础(边框效果)
  • 【Unity笔记】Unity 编辑器扩展:一键查找场景中组件引用关系(含完整源码)(组件引用查找工具实现笔记)
  • Prompt 结构化提示工程
  • React组件测试完全指南:从入门到实践
  • vue3+dhtmlx 甘特图真是案例
  • 数据一致性问题剖析与实践(二)——单机事务的一致性问题
  • 数据为基:机器学习中数值与分类数据的处理艺术及泛化实践
  • MacOS中安装Python(homebrew,pyenv)
  • 科普|结石疼痛背后的危机信号:疼痛消失≠警报解除
  • 何以中国|福建武夷山:千年茶道的文旅“破圈”与新生
  • 特斯拉一季度净利下滑七成,马斯克表态将继续倡导关税下调
  • 广东江门公布“小客车坠海致3死”事故评估报告,司机被判三年缓五年
  • 视频·世界读书日|王弘治:信息轰炸也会让文化体力透支
  • 东方富海陈玮: 什么样的创业者能让天使投资人愿意下注