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

【Java虚拟机】JVM内存模型

JVM的内存模型

JVM的运行时内存主要分为Java虚拟机栈,堆,本地方法栈,程序计数器,元空间五个部分,还有一部分是直接内存,是操作系统的本地内存,也是可以直接操作的。

Java虚拟机栈

每个线程都有一个独立的虚拟机栈,并且在方法执行前都会在栈中创建一个栈帧,用来存储该方法的一些信息。

Java堆

堆是JVM中最大的一块区域,它是所有线程共享的,用来存储对对象的实例。每当遇到一个new关键字时,都会在堆中为其分配一块内存

本地方法栈

与虚拟机栈类似,本地方法栈是服务于本地方法的,当方法执行时也会创建一个栈帧。

程序计数器

程序计数器可以看作是Java程序运行字节码文件的行号指示器。它用来存储正在执行的Java方法的JVM指令地址。当执行本地方法时,它的值为null。

元空间

Java8以后,方法区被元空间所取代,它用来存放已将被虚拟机加载的类信息,常量,静态变量等信息。虽然它被称为堆的逻辑部分,但是还有“非堆”的别名,可以不实现垃圾回收

运行时常量池

运行时常量池是方法区的一部分,用于存放编译时产生的各种字面量和符号

直接内存

通过NIO类引入,极大提高了IO性能。直接内存的使用受到本机总内存的限制。

JVM内存模型里堆和栈有什么区别

  • 用途不同:每当方法执行时都会在栈中创建一个栈帧,用来存放该方法的信息。而堆是用来存放实例化对象的。每当使用new关键字创建一个新对象时,都会在堆中为其分配一片内存
  • 生命周期不同:栈中的栈帧有明确的生命周期,在方法被调用时被创建,方法运行结束后被清除。而堆中没有明确的生命周期,当垃圾回收器监测到该对象不再被引用时,会将该对象进行清除
  • 空间不同:栈的空间相对较小,通常是不可变的。而堆的空间较大,而且是可扩展的
  • 存取速度不同:栈采用的是先进后出的数据结构,操作简单,存取速度较快。而堆的存取速度较慢,并且垃圾回收也需要消耗一定的时间
  • 可见性:栈是独立的,各个线程间是不可见的。而堆是被所有线程所共享的。

栈中存的是指针还是对象

存的是对象的引用

堆分为哪几部分

新生代

新生代又可以划分为伊甸区和幸存者区,幸存者区又可以划分为两个大小相等的区域,s0,s1。当一个新的对象被创建时通常首先会分配到伊甸区,当伊甸区满时会触发一次垃圾回收,在每次垃圾回收后都会将存活的对象移动到s0或s1。二者充当对象的中转站。帮助区分长期存活和短期存活的对象。

老年代

当经过多次垃圾回收后仍然存活的对象会被移动到老年代,这里的full GC频次较低,但是时间比较长。老年代的空间通常比新生代要大,用来存放更多长期存活的对象。

元空间

用来存放已将加载的类信息,常量,静态变量等信息。它不在堆内存中,而是在本地内存。解决了永久代的内存泄漏问题

大对象区

有些JVM的实现还有大对象区,用来专门存放放大对象

如果有一个大对象,一般存放在哪里

一般直接存放在老年代中,原因有两点

  • 第一:新生代空间较小,如果直接存放大对象会导致内存不足,频繁出发垃圾回收,而垃圾回收涉及到对象的复制和转移,造成大量消耗。放入老年代可以减少新生代的压力。
  • 第二:如果直接将大对象放入新生代,频繁将大对象进行分配和清理,会产生大量内存碎片。导致下次为大对象分配空间时找不到连续的大空间,造成内存溢出。而老年代空间较大,能够减少内存碎片的产生。

程序计数器为什么是私有的

Java程序允许多个线程同时运行。当线程1和线程2同时运行时,CPU就会为其分配时间片,当执行完线程1的时间片后代码还没有执行完毕,会先去执行线程2 的时间片。执行完毕后再回到线程一执行剩余代码。程序计数器就起到记录程序执行字节码指令地址的作用。因此是私有的

方法区中方法的执行过程

  • 方法解析调用:首先JVM会根据方法的符号引用找到方法的实际地址
  • 栈帧创建:执行方法前先在栈中创建栈帧用来存储该方法的相关信息
  • 执行方法:执行方法内的字节码指令
  • 处理返回结果:方法执行完毕后,可能会将执行结果返回给调用者。清除栈帧,回复调用者的执行环境

String保存在哪里

String保存在字符串常量池中,该对象是不可变的,被其他引用所共享

String s=new String(“abc”)涉及到哪些内存区域

首先我们看到new关键词,我们可以知道该对象是在堆内存中创建的。然后abc是被fianl所修饰的,我们会先去字符串常量池中去查询是否存在该字符串,如果存在直接返回引用,如果不存在会先在常量池中创建该字符串,并返回引用。因此分两种情况:
第一种情况:字符串常量池中存在,那么只涉及到一个对象的创建。
第二种情况:符串常量池中不存在,那么涉及到两个对象的创建。

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

  • 强引用:指代码中普遍存在的赋值方式,这种引用永远不会被垃圾回收
  • 软引用:指需要带不是必须的那些对象,当系统内存溢出前会将其进行垃圾回收
  • 弱引用:比软引用还要低一点,当下一次垃圾回收时,一定会被回收掉
  • 虚引用:最弱的引用,也被称为幻影引用。需要配合refenence queue使用。

弱引用可以用在哪里

弱引用通常用来创建非强制性对象引用,这些对象会在内存不足时自动进行垃圾回收。
使用场景:

  • 实现缓存:通过弱引用实现缓存可以在JVM需要更多内存时自动清理掉这些缓存对象
  • 对象池:使用弱引用管理这些不被使用的对象时,他们就可以被垃圾回收,释放内存
  • 避免内存泄漏:当一个对象长期不被使用时,可以使用弱引用防止该对象长期存在,导致内存泄漏。
http://www.lryc.cn/news/619966.html

相关文章:

  • uniapp跨端性能优化方案
  • 中科米堆CASAIM蓝光三维扫描仪用于焊接件3D尺寸检测
  • GDB命令笔记
  • 【React】use-immer vs 原生 Hook:谁更胜一筹?
  • Chrome 插件开发实战
  • AutoCAD 各版本与插件合集详解:Architecture、Plant 3D、Civil 3D 等
  • CNN卷积神经网络预测手写数字的Pytorch实现
  • games101 第三讲 Transformation(变换)
  • 人工到智能:塑料袋拆垛的自动化革命 —— 迁移科技的实践与创新
  • AI一键抠图软件--Digiarty.AIArty.Image.Matting
  • MySQL数据库知识体系总结 20250813
  • 数据库连接池如何进行空闲管理
  • TeamViewer 以数字化之力,赋能零售企业效率与客户体验双提升
  • “我店模式”:零售转型中的场景化突围
  • 【k8s】k8s pod调度失败原因列表、Pod 完整的状态类型列表
  • TDengine IDMP 基本功能(4. 实时分析)
  • 【金仓数据库产品体验官】_从实践看金仓数据库与 MySQL 的兼容性
  • Java开发主流框架搭配详解及学习路线指南
  • Pytest项目_day14(参数化、数据驱动)
  • VR中image或者文字一直浮现在眼前
  • Flutter 多模块 + 组件化架构设计实践
  • 使用HtmlAgilityPack+PuppeteerSharp+iText7抓取Selenium帮助文档
  • PCIE 配置空间 拓展能力 定义
  • mac环境下安装git并配置密钥等
  • 20250813测试开发岗(凉)面
  • 19. 重载的方法能否根据返回值类型进行区分
  • 完整源码+技术文档!基于Hadoop+Spark的鲍鱼生理特征大数据分析系统免费分享
  • Java Spring框架最新版本及发展史详解(截至2025年8月)-优雅草卓伊凡
  • 【C#】利用数组实现大数数据结构
  • 云电竞盒子对游戏性能有影响吗?