Java虚拟机JVM知识点(持续更新)

news2025/4/2 21:30:43

JVM内存模型

介绍下内存模型

根据JDK8的规范,我们的JVM内存模型可以拆分为:程序计数器、Java虚拟机栈、堆、元空间、本地方法栈,还有一部分叫直接内存,属于操作系统的本地内存,也是可以直接操作的。

详细解释一下

  • 程序计数器:可以看作是当前线程所执行的字节码的行号指示器,用于存储当前线程正在执行的Java方法的JVM指令地址。
  • Java虚拟机栈:每个线程都有一个独立的Java虚拟机栈,生命周期和线程相同。每个方法在执行时都会创建一个栈帧,用于存储局部变量表,操作数栈,动态链接,方法出口等,可能抛出OOM和StackOverflowError异常。
  • 本地方法栈:与Java虚拟机栈类型,主要为虚拟机使用到的Native方法服务,在HotSpot虚拟机中和Java虚拟机栈合二为一。本地方法执行时也会创建栈帧,同样也可以抛出OOM和StackOverflowError异常。
  • 方法区(元空间):在JDK8以后的版本中,方法区被元空间取代,使用本地内存。用于存储已被虚拟机加载的类信息、常量、静态变量等数据。虽然方法区被描述为堆堆逻辑部分。方法区可以选择不进行垃圾回收。同样可以抛出OOM和StackOverflowError异常。
  • Java堆:在JVM最大的一个部分,被所有线程所共享,当虚拟机启动时,用于存放所有的对象实例。从垃圾回收的角度,分为新生代和老年代,新生代分为伊甸区(Eden)和幸存区(Survivor分为From Survivor和To Survivor),如果在堆中没有内存完成实例分配,并且堆也无法扩展时会OOM。
  • 运行时常量池:是方法的一部分,用于存放编译期间生成的各种字面量和符号引用,具有动态性。
  • 直接内存:不属于JVM运行时数据区的一部分,通过NIO引入,是一种堆外内存,可以显著提高i/o性能。

JVM内存模型中堆和栈的区别

  • 用途:栈主要用于存储局部变量、方法参数的调用、方法返回地址以及一些临时数据。每当一个方法被调用,就会创建一个栈帧,用于存储方法的信息,方法执行完毕,栈帧也会被移除。堆用于存储对象的实例,当你使用new去创建一个对象时,对象实例就会在上面分配空间。
  • 生命周期:栈中的数据具有确定的生命周期,当一个方法结束调用时,其对应的帧栈就会被移除,栈中存储的局部变量也就会消失。堆中的对象没有固定的生命周期,闲置对象会在垃圾回收机制下被回收。
  • 存取速度:栈的存取速度比堆快,因为栈遵循先进后出FIFO的原则,操作简单快速。堆的存取速度较慢,因为对象在对上分配和回收需要更多的时间,垃圾回收机制也会影响性能。
  • 存储空间:栈的空间相对较小,且较为固定,由操作系统管理。当栈溢出时,通常因为递归过深或者局部变量过大。堆的空间较大,动态扩展,由JVM管理,堆溢出通常由于创建了太多的大对象未及时收回。
  • 可见性:栈中的数据对线程是私有的,每个线程有自己的栈空间。堆中的数据对线程是共享的,所有线程都可以访问堆上的对象。

栈中存储的到底是指针还是对象

在JVM内存模型中,栈主要用于管理线程的局部变量和方法的上下文调用,而堆是粗处所有类的实例和数组。

当我们在讨论存储时,实际上栈中存储的是方法执行时的基本数据类型和对象的引用,这里注意是对象的引用,不是对象本体,指向堆中对象的实例。

堆分为哪几部分呢

  • 新生代:新生代分为Eden伊甸区和幸存区。在伊甸区中,大多数新创建的对象都会放在这里,Eden区相对较少,当Eden区满时,会触发一个Minor GC(轻GC)。在幸存区中,通常分为两个大小相等的部分,每次Minor GC时,存活下来的对象会被移动到其中的一个幸存区,以继续他们的生命周期。
  • 老年代:存放过一次或多次Minor GC仍存活的对象会被移动到老年代。老年代的生命周期较长,因此Full GC发生频率较低,但是执行时间比Minor GC长,老年代空间比新生代长。
  • 元空间:从Java8开始,永久代被元空间取代,用于存储类的元信息,如类的结构信息等。元空间不在堆红,而是使用了本地内存,解决了永久代OOM的问题。
  • 大对象区:在某些JVM实现中引入了大对象区,指需要大量连续的内存空间的对象,如大数组,这类对象直接放在老年代,避免年轻代的晋升而导致内存碎片化。

方法区的执行过程

  • 解析方法调用:JVM会根据方法的符号引用找到实际方法地址。
  • 栈帧创建:在调用一个方法前,JVM会在当前线程的Java虚拟机栈中为该方法分配一个新的栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口信息。
  • 执行方法:执行方法内的字节码命令,涉及的操作可能包括局部变量的读写等操作。
  • 返回处理:方法执行完毕后,可能会返回一个结果给调用者,并清理当前栈帧,恢复调用者的执行环境。

String保存在那里?

String是包存在字符串常量池中,不同于其他对象,他的值是不可变的,可以被多个引用共享。

引用类型有哪些?有什么区别

  • 强引用类型:是代码中普遍的赋值方式,比如A a = new A();这样的发过誓。强引用关联的对象,永远不会被垃圾回收器回收。
  • 软引用类型:可以用SoftReference来描述,指的是那些有用但是不是必须要的对象。系统在发生内存溢出前会针对这样的对象进行回收。
  • 弱引用:可以用WeakReference来描述,他的强度比软引用低,弱引用的对象下一次GC的时候一定会被回收,不管内存是否足够。
  • 虚引用:幻影引用,是最弱的引用关系,他必须和ReferenceQueue一起使用,当GC发生时,虚引用也会被回收。可以用虚引用来管理堆外内存。

弱引用了解吗?举例说明

Java中的弱引用是一种引用类型,他不会阻止一个对象被垃圾回收。

  • 缓存系统:弱引用常用来实现缓存,特别是当希望缓存项能够在内存压力下自动释放时。如果缓存的大小不受控制,可能会导致内存溢出。使用弱引用来维护缓存,可以让JVM在需要更多内存的时候自动清理这些对象。
  • 对象池:在对象池中,弱引用可以用来管理那些暂时不用的对象。当对象不再被强引用时,他可以被垃圾回收,释放内存。
  • 避免内存泄漏:当一个对象不应该被长期引用时,使用弱引用可以防止该对象被意外的保留,避免的潜在的内存泄漏。

内存泄漏和内存溢出的理解

内存泄露:内存泄露通常是在程序运行中不再使用的对象仍然被引用,从而无法被垃圾回收器回收,从而导致可用内存逐渐变少,虽然在Java中,垃圾回收机制会自动回收不再引用的对象,但是仍有对象不会被回收,最终导致程序内存不断增加。

导致内存泄漏的原因

  • 静态集合:使用静态的数据结构存储对象,且没有清理。
  • 事件监听:未取消对事件的监听,导致对象被持续引用
  • 线程:未停止的线程可能持有对象的引用,无法被回收

内存溢出:内存溢出指的是Java虚拟机在申请内存时,无法找到足够的内存,最终引发OOM。

内存溢出主要原因

  • 大量对象创建:程序中不断创建大量对象,超出JVM堆的限制。
  • 持久引用:大型数据结构长时间持有对象的引用,导致内存积累
  • 递归调用:深度递归导致栈溢出

JVM内存结构中有哪几种内存溢出的情况

  • 堆内存溢出:当出现OOM时,就是堆内存溢出了,原因是代码中可能存在大对象分配。或者发生了内存泄漏,导致多次GC之后,仍无法找到一个合适的空间存放当前对象。
  • 栈内存溢出:如果我们写一个程序不断的递归调用,而且没有退出条件,就回导致不断的进行压栈。类似于这种情况会JVM会抛出:SOF。如果JVM试图扩展栈空间失败,则直接报出OOM。
  • 元空间溢出:出现这个异常是系统的代码非常多或者引用了过多的第三方包或者通过动态代码加载类的操作,导致元空间内存被压满
  • 直接内存溢出:在使用ByteBuffer会使用到,很多JavaNIO的框架(Neety和Vert.x)被封装为其他的方法会抛出OOM。

类初始化和加载

创建对象的过程

  1. 类加载检查:虚拟机收到一条new指令时,首先将去检查这个指令的参数能否在常量池中定位到一个类的符号引用。并检查这个符号引用代表的类是否被加载、解析和初始化过。如果没有则必须先进行相应的类加载工程。
  2. 分配内存:在类加载检查过程后,接下来虚拟机将为新生代分配内存。对象所需的内存大小在类加载后方可确定,将对象所需要的空间从Java堆中划分出来。
  3. 初始化零值:内存分配完成后,虚拟机需要将分配到的内存空间初始化为0值,这一步保证了对象的实例字段在Java中可以不赋值就可以直接使用,程序能够能访问到这些字段的数据类型所对应的零值。
  4. 进行必要设置(对象头):初始化零值完成之后,虚拟机需要对对象进行必要的设置。也就是初始化对象头。
  5. 执行init方法:在上面工作完成后,在JVM看来,一个对象已经执行完毕了。但是在程序看来,才刚刚开始。需要根据程序设计者的思路来初始化对象。

对象生命周期

  • 创建:对象通过关键字new在堆内存中被初始化,构造函数被调用,对象内存空间被分配。
  • 使用:对象被引用并执行相应操作。
  • 销毁:当对象部呗引用时,通过垃圾回收机制自动回收对象所占用的内存空间。

类加载器都有哪些

  • 启动类加载器:这是最顶层的加载器,负责加载Java的核心库,是使用C++编写的,是JVM的一部分,启动类加载器无法被Java程序直接引用。
  • 扩展类加载器:他是Java语言实现的,继承自ClassLoader类,负责加载Java扩展目录下的jar包和类库,扩展类加载器由启动类加载器加载,并且父加载器就是启动类加载器。
  • 系统类加载器:这也是Java语言实现的,负责加载用户类路径上的指定类库,是我们平时编写Java默认使用的加载器。
  • 自定义类加载器:用户定制的类加载器。

这些类加载器之间的关系形成了双亲委派模型,核心思想是当一个类加载器收到类加载请求时,首先不去自己尝试加载这个类,而是把这个请求委派给副加载器去完成,每一层都是如此,因此所加载请求最终都应该传送到顶层加载器中。

双亲委派到作用

  • 保证类的唯一性:通过委托机制,保证每一个加载请求都会传递到启动类加载器,避免不同的加载器加载相同的类,保证了Java核心库的一致性
  • 保证安全性:防止不可信的类假冒核心类。因为都会被委托到顶层的启动类加载器。
  • 隔离和层次划分:双亲委派模型支持不同层次的类加载器服务于不用的类的加载请求。
  • 简化加载流程:通过委派,大部分类能够被正确的类加载器加载,减少了每个加载器需要处理类的数量,简化加载过程。

讲一下类加载的过程

  • 加载:通过类的全限定名获取到类的.class文件的二进制字节流,将二进制字节流所代表的静态存储结构转化为方法区运行时的数据结构,在内存中生成一个代表该类的Java.lang.Class对象,作为方法区这个类的各种入口。
  • 连接:
    • 验证:验证这个类的字节流内所包含的信息是否符合当前虚拟机要求。
    • 准备:将静态资源赋0值
    • 解析:将符号引用直接替换为直接引用
  • 初始化:初始化是整个类加载过程中的最后一个阶段,初始化阶段简单来说执行构造器方法们要注意这个构造器不是开发者写的,是编译器生成的。
  • 使用类或者对象
  • 卸载:当一个类的所有实例都被回收,也就是Java堆中不存在该类的任何实例,加载类的ClassLoader已经被回收。类对应的Java.lang.Class对象没有任何地方被引用,无法在任何地方通过反射获取对象。

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

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

相关文章

【计算机网络】HTTP与HTTPS

文章目录 1. HTTP定义2. HTTP交互3. HTTP报文格式3.1 抓包工具-fiddler3.2 抓包操作3.3 报文格式3.3.1 请求报文3.3.2 响应报文 4. URL5. 请求头中的方法6. GET和POST的区别7. HTTP报头7.1 Host7.2 Content_Length7.3 Content_Type7.4 User-Agent(UA)7.5 Referer7.6 Cookie 8 状…

数据结构:树的5种存储方案详解(C语言完整实现)

数据结构中的树结构常用来存储逻辑关系为 "一对多" 的数据。树结构可以细分为两类,分别是二叉树和非二叉树(普通树),存储它们的方案是不一样的: 二叉树的存储方案有 2 种,既可以用顺序表存储二叉…

【蓝桥杯】 枚举和模拟练习题

系列文章目录 蓝桥杯例题 枚举和模拟 文章目录 系列文章目录前言一、好数: 题目参考:核心思想:代码实现: 二、艺术与篮球: 题目参考:核心思想:代码实现: 总结 前言 今天距离蓝桥杯还有13天&…

WebGL图形编程实战【3】:矩阵操控 × 从二维到三维的跨越

上一篇文章:WebGL图形编程实战【2】:动态着色 纹理贴图技术揭秘 仓库地址:github…、gitee… 矩阵操控 矩阵变换 回到前面关于平移缩放、旋转的例子当中,我们是通过改变传递进去的xy的值来改变的。 在进行基础变换的时候&…

如何把数据从SQLite迁移到PostgreSQL

## 如何把数据从SQLite迁移到PostgreSQL 文章目录 1、DB-Engines 中的SQLite 和 PostgreSQL2、SQLite安装和测试2.1、编译安装SQLite2.2、数据测试 3、Postgresql安装和测试3.1、编译安装postgresql3.2、测试 4、pgloader安装5、数据迁移和验证5.1、准备参数文件5.2、数据迁移…

Qt使用QGraphicsView绘制线路图————附带详细实现代码

文章目录 0 效果1 核心1.1 简单示例1.1.1 解读 1.2 创建用户交互1.2.1 完整示例 1.3 创建图形元1.3.1 绘制直线1.3.2 绘制贝塞尔曲线1.3.3 绘制图片 1.4 移动的小车 2 使用自定义视图类参考 0 效果 视图中包含线路、道岔、信号灯、火车。 下图为站点信号灯: 下图…

【Linux】调试器——gdb使用

目录 一、预备知识 二、常用指令 三、调试技巧 (一)监视变量的变化指令 watch (二)更改指定变量的值 set var 正文 一、预备知识 程序的发布形式有两种,debug和release模式,Linux gcc/g出来的二进制…

【数据分享】2000—2024年我国乡镇的逐年归一化植被指数(NDVI)数据(年最大值/Shp/Excel格式)

之前我们分享过2000-2024年我国逐年的归一化植被指数(NDVI)栅格数据,该逐年数据是取的当年月归一化植被指数(NDVI)的年最大值!另外,我们基于此年度栅格数据按照行政区划取平均值,得到…

Shell 不神秘:拆解 Linux 命令行的逻辑与效率

初始shell shell的概述 什么是shell 本质 shell本质是脚本文件:完成批处理。 比如 有一个文件 中十个文件,这十个文件中每个文件又有是个子文件,由人来处理,很麻烦,但如果写一个脚本文件,让脚本来替我…

win 远程 ubuntu 服务器 安装图形界面

远程结果:无法使用docker环境使用此方法 注意要写IP和:数字 在 ubuntu 服务器上安装如下: # 安装 sudo apt-get install tightvncserver # 卸载 sudo apt purge tightvncserver sudo apt autoremove#安装缺失的字体包: sudo apt update s…

大模型高质量rag构建:A Cheat Sheet and Some Recipes For Building Advanced RAG

原文:A Cheat Sheet and Some Recipes For Building Advanced RAG — LlamaIndex - Build Knowledge Assistants over your Enterprise DataLlamaIndex is a simple, flexible framework for building knowledge assistants using LLMs connected to your enterpris…

【Qt】游戏场景和图元

一:图元 advance函数: 在 Qt 框架里,QGraphicsItem 是用于在 QGraphicsScene 中绘制图形项的基类。advance(int phase) 是 QGraphicsItem 类的一个虚函数,其主要用途是让图形项在场景的动画或更新过程里完成特定的逻辑操作。 p…

开源的CMS建站系统可以随便用吗?有什么需要注意的?

开源CMS建站系统虽然具有许多优点,但并非完全“随便用”。无论选哪个CMS系统,大家在使用的时候,可以尽可能地多注意以下几点: 1、版权问题 了解开源许可证:不同的开源CMS系统采用不同的开源许可证,如GPL、…

初始ARM

ARM最基础的组成单元。 最小系统:能系统能够正常工作的最少器件构成的系统 。 一、CPU基础定义 1. 核心定位 计算机三大核心部件: CPU(运算与控制)内部存储器(数据存储)输入/输出设备(数据交互…

DataPlatter:利用最少成本数据提升机器人操控的泛化能力

25年3月来自中科院计算所的论文“DataPlatter: Boosting Robotic Manipulation Generalization with Minimal Costly Data”。 视觉-语言-动作 (VLA) 模型在具身人工智能中的应用日益广泛,这加剧对多样化操作演示的需求。然而,数据收集的高成本往往导致…

诠视科技MR眼镜如何安装apk应用

诠视科技MR眼镜如何安装apk应用 1、使用adb工具安装1.1 adb工具下载1.2 解压adb文件1.3 使用adb安装apk1.4 常用adb命令 2、拷贝到文件夹安装 1、使用adb工具安装 1.1 adb工具下载 点击下面的链接开始下载adb工具,下载结束以后解压文件。 下载链接: https://down…

搭建前端环境和后端环境

搭建前端环境 ①、安装vscode,并安装相应的插件工具 ②、安装node.js,可以选择当前版本,或者其他版本 ③、创建工作区 创建一个空文件夹,然后通过vscode工具打开,保存为后缀名为.code-workspace ④、从gitee…

Polhemus FastScan 单摄像头3D激光扫描器

FastSCAN Cobra是Polhemus公司研制的手持激光扫描仪。与以前的产品比较,它节省了30%的费用,体积也减小了一半 ,但仍然保留了所有功能,使用和携带都更加方便。作为超小的手持激光扫描仪,FastSCAN Cobra对扫描三维物体具…

召唤数学精灵

1.召唤数学精灵 - 蓝桥云课 问题描述 数学家们发现了两种用于召唤强大的数学精灵的仪式,这两种仪式分别被称为累加法仪式 A(n) 和累乘法仪式 B(n)。 累加法仪式 A(n) 是将从1到 n 的所有数字进行累加求和,即: A(n)12⋯n 累乘法仪式 B(n) …

2025图像处理和深度学习国际学术会议(IPDL 2025)

重要信息 官网:www.IPDL.xyz 时间:2025年4月11-13日 地点:中国-成都 简介 随着深度学习和图像处理技术的迅速发展,相关技术的应用逐渐渗透到各个行业,如医疗影像分析、自动驾驶、安防监控和智能制造等。这些应用的…