对象生命周期与内存模型

内存模型是随着越来越丰富和复杂的对象生命周期要求的发展而发展起来的。

最初的内存模型完全是线性的,静态的,一个程序运行时所有需要的对象都是在运行前完全准备好了的,运行完了时释放掉。典型的代表就是Fortran语言。这种语言的运行性能非常高(当然了,没有任何别的消耗嘛),但是表达能力受到限制(毕竟,要求静态的确定一切对象和内存的绑定关系)。最明显的一个限制就是没办法支持递归。这种内存模型支持的对象的生命周期跟应用程序的生命周期完全一致。同生共死,天下大同。

Alogal的出现引入了一个强大的概念: lexical scope,内存模型也相应的出现了细分概念:栈。栈就是那种先进后出的容器,它完美的切合了lexical scope。同时,栈上的对象的生命周期也很清晰,进栈是出生,出栈时死亡。栈这个概念是如此的清晰、容易理解,而且如此的强大,导致现代各种语言的内存模型中,栈都占有非常显著的地位。栈自然地解决了递归问题。栈上对象的生命周期的管理完全可以自动化而高效的完成。但是,栈仍然不足以满足某些对象生命周期的要求。

我先说说这是那种样子的生命周期。简单的说,栈对于共享的对象的生命周期无能为力。也就是说,某个对象,在多个平级的或者嵌套的scope之间共享,而栈却没办法解决。非得用栈来满足这种需求的话,会导致大量的memcpy,导致性能的低下。而且还是模拟的解决这个问题。其实,对于参数和返回值,基于栈架构的内存模型和对象就是采用复制和反向复制的方式来完成的。

面对这个挑战(共享对象生命周期问题),第一个反应就是避免共享,其实就是我前面说的完全副本的方式。这种方式在一定程度上有效,不过,对于大对象是非常不划算的。

C 和Pascal语言来了,这类语言提供了另一个概念叫做堆(其实,堆这个概念并不是它们最先引入的,但是是由它们发扬光大的)。从此内存模型分裂为两个界限明显的类型:栈和堆。堆就是那种随机进随机出的对象的栖息之地。也就是说,这种对象的生命周期不再可以向栈对象那样自动高效的管理了。有了这样的基础设施,共享对象就变得简单了。创建一个堆对象,然后A使用之,只要不销毁,B就可以使用之,这样,该对象就可以由A和B共享了。当然,牵扯到共享,必然会涉及到同步和互斥的问题。也就是A和B究竟怎样访问该对象的问题。一般来说,采取的策略是是把并发访问串行化的技术。由此导出很多互斥的技术。我们就不在这上面纠缠了。我们关注的是对象本身的生命周期,也就是说。这个可以共享的对象的生、死问题。由谁负责生(创建)似乎大家都没有什么抱怨的,由第一个要用该对象的负责,这也不会导致麻烦。原因是:如果你不负责生,那么该对象就不存在,你也就没办法使用了。:)由谁负责死(销毁)呢。这个看起来也很简单:最后一个用完了就销毁。而事实上也确实就这么简单。但是这儿有一点麻烦。跟创建不一样,创建不会被忘记,而销毁会。忘记销毁对象对自己没有伤害,所以,就选择忘记吧。:)这不是拉屎不擦屁股的问题。这个不难受。

这样说吧。现代的语言按照由谁负责堆对象的销毁问题大致可以分成两大类,一类叫做有垃圾回收的,一类没有。有垃圾回收的那一类是由运行环境(运行时)负责销毁共享对象,没有垃圾回收的那一类由程序自己负责销毁共享对象。对程序员来说,当然有垃圾回收的语言跟友好了。但问题是垃圾回收需要首先搞定哪一些共享对象不再需要了。这是一个比较困难的问题。而对于没有垃圾回收的那种语言来说,程序自己逻辑上应该很清楚哪一些对象不再需要了,可以销毁了。

一般情况下,我们把那些由运行时负责销毁共享对象的那些堆叫做托管堆,负责销毁共享对象的运行时的一部分叫做垃圾回收器(GC),也就是说,托管堆就使那种委托给GC管理的堆。
相应的,没有委托给GC管理的堆就是普通的堆了。普通堆有应用程序自己负责销毁共享对象。

上面的描述还没有提到的一个问题是:对象究竟在什么时候销毁?由于一个对象不立即销毁一般不会导致什么重大的问题,所以销毁的时机相对来说可以很灵活。当然,肯定是在最后一个使用了以后。但是以后是多久呢?是立即销毁?还是延迟一段时间?如果是延迟,那么究竟延迟多长时间?还是更进一步的说延迟不定长的时间?

由于一般情况下,我们认为批量销毁比一个一个销毁要快一些,所以一个指导性的方案就是等到垃圾(生命周期应该已经结束了的共享对象)积累到一定的量以后(只要不影响程序的正常运行)批量销毁。这一般会导致销毁的不定长延迟。

上面说了:“由于一个对象不立即销毁一般不会导致什么重大的问题,所以销毁的时机相对来说可以很灵活。”。注意这个句子里面的“一般”这个字眼,这也就是说:在特殊情况下,不立即销毁会导致重大问题。那种情况是特殊情况呢?就是那种销毁对象的动作还带有别的副作用,而这个副作用会影响以后程序的运作行为的情况。这种情况在使用C++的RAII的时候是基本情况。

现在错略的说说垃圾回收的基本方法。

我们把托管堆中的对象以及对象的互相引用关系看作是一个“图”(数学上定点和边的集合),应用程序的栈上有一些引用引用到这个图的某些顶点。从GC的角度来看,应用程序的作用就是不断地改变图的连通性,故此把应用程序叫做Mutator。GC就是通过查看图的连通性把那些孤立的顶点(就是那种生命周期结束的共享对象)回收的。

那么,我们怎么知道图的连通性的呢?

1、可以通过从根集跟踪。所谓根集,就是应用程序栈上的引用集合。我们知道,这种跟踪肯定可以搞定图的连通性,但是,这要求我们能够区分什么是引用,而什么不是。
2、每次应用程序修改图的连通性的时候,记录下来。这样GC就可以直接销毁那些孤立的顶点了。
第一种方式是最常用的方式,或者甚至可以这样说,第二种方式根本没人用。

不过,第二种方式的某种变形方式用的人却很多。那就是RefCount。第二种方式把集中存放的连通图信息分散的放置到各个共享对象身上,让他们记住自己被多少个别的对象引用就行了。这样当它发觉自己被0个对象引用的时候,就自裁。

这个方式看起来非常好,也非常干净,但是有两个缺点。一是性能。每一次引用一个对象,都需要增加这个引用计数,放弃引用的时候得减少之。影响了性能。另一个是对于环形图的无能为力。
LeRobot 官方论文:一个用于端到端机器人学习的开源库 本文介绍了一个名为LeRobot的开源库,旨在解决机器人学习领域的碎片化问题。该库提供了端到端的技术栈,包括统一的机器人中间件API、标准化的数据集格式(LeRobotDataset)、优化的推理栈以及多种最先进机器人学习算法的实现。LeRobot支持多种低成本开源机器人平台(如SO-10X、ALOHA-2等),通过共享中间件实现便捷的遥操作和数据收集。其数据集格式已广泛应用于社区,截至2025年9月已有16,000多个数据集公开共享。该库还支持流式处理大规模数据,降低了研究门槛。在模型方面,LeRobot 阅读详情

相关推荐

时间序列分析:ARCH、GARCH、TGARCH与DCC-GARCH波动率模型(含代码)

关注TGARCH模型和DCC-GARCH的应用,通过在沪深300和中证500指数上应用TGARCH和DCC-GARCH模型,揭示这两个指数之间的条件异方差及动态相关性的变化规律。

celiaweiwei的博客 1万+

从一个Java对象看JVM内存模型及对象生命周期

【JVM系列4】new Object()到底占用几个字节,看完这篇就彻底明白了 package com.zwx.jvm; public class HeapMemory { private Object obj1 = new Object(); public static void main(String[] args) { Object obj2 = new Object(); } } 上面的代码中,obj1 和obj2在内存中有什么区别? 答: 这个obj

commonBean的专栏 359

手把手教你用GD32F407VET6的EXMC驱动外部SRAM,搞定大内存需求

本文详细介绍了如何使用GD32F407VET6的EXMC外设驱动外部SRAM,解决嵌入式开发中的大内存需求问题。通过硬件连接方案、EXMC时序配置与初始化步骤,以及软件集成与内存管理技巧,帮助开发者快速实现内存扩展。特别适合需要处理图形显示缓冲、音频处理等大内存场景的GD32F407开发者。

weixin_30752699的博客 346

fortran内存不足的解决方法

先点击项目 然后点项目属性 然后设置如图,就能解决问题了

weixin_43158984的博客 4232

CoppeliaSim(原V-REP)新手上路

CoppeliaSim(原V-REP)是一个机器人仿真平台,里面有很多来自别的公司的机器人模型以及完备的物理引擎,我们可以通过python,c++,matlab等语言控制里面的机器人。,您也可以在官网中Downloads里找您需要的版本,一般只需要下载EDU版本就可以了,我下载的是v4.1.0 windows EDU版本。在版本V4之前,CoppeliaSim叫V-REP,在官网可以下载到之前的V-REP版本。

qq_37051669的博客 4万+

【纯实战】C#基于TCP/IP实现三菱PLC MC协议完整通信(含完整源码+通信原理+避坑指南)

MC协议是三菱电机为旗下MELSEC系列PLC量身定制的以太网专用通信协议,本质是一套基于TCP/IP的应用层协议规范,专门用于实现上位机(PC/工控机)与PLC之间的双向数据交互,支持对PLC的软元件(X/Y/M/D/W/T/C等)进行读、写、批量读写等核心操作,同时支持PLC状态查询、程序启停等控制指令。重要:三菱PLC的MC协议默认基于TCP 4999端口通信,部分新版本FX5U/Q系列也支持TCP 5000端口,核心通信逻辑一致。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 895

C++内存对象大会战

 作者: peter_jiang 来源:csdnblog          如果一个人自称为程序高手,却对内存一无所知,那么我可以告诉你,他一定在吹牛。用C或C++写程序,需要更多地关注内存,这不仅仅是因为内存的分配是否合理直接影响着程序的效率和性能,更为主要的是,当我们操作内存的时候一不小心就会出现问题,而且很多时候,这些问题都是不易发觉的,比如内存泄漏,比如悬挂指针。笔者今天在这里并不是要讨论

domisou 836

EtherCAT主站SOEM -- 29 -- STM32F767-SOEM通过 CSP模式(周期同步位置模式)控制一个电机转圈圈

以上就是EtherCAT主站SOEM – 29 – STM32F767-SOEM通过 CSP模式(周期同步位置模式)控制一个电机转圈圈的内容。有不明白的地方欢迎留言;有建议欢迎留言,我后面编写文档好改进。创作不容,如果文档对您有帮助,记得给个赞。

常驻客栈的博客--嵌入式EtherCAT 2242

JVM内存模型--对象生命周期

什么时候才会进行垃圾回收?关注内存的回收,是选择收的多还是选择垃圾回收线程耗时短回收时间短到何种程度,1次网络延迟时间是多久CPU使用率很高的情况下,适当降低垃圾回收的频率,有一系列的问题。

weixin_43860222的博客 717

华为OD机试真题 新系统 2026-08-02 C++ 实现【战士技能规划设计】

你为一款动作游戏设计战士角色的技能。战士每个技能会消耗不同能量,释放技能有两个约束:连续释放技能数量不能超过 m 个,技能能量总和不能超过能量上限 k;如果超过则必须中断当前技能,进入调息状态,也就是分段。

MISAYAONE的博客 75

openbmc mctp i3c适配步骤

本文介绍了在Intel OKS平台下,BMC作为I3C从设备如何适配MCTP over I3C的实现方法。主要内容包括:1)关键术语解释,如MDB(Mandatory Data Byte)值为0xAE,DCR(Device Characteristics Register)和BCR(Bus Characteristics Register)的设置;2)适配流程说明,包括BMC作为控制器主节点分配地址后成为MCTP端点,CPU作为总线所有者的角色转换;3)测试验证步骤,展示通过mctp-client工具发送指

wit_yuan的专栏 132

从C到Java的面向对象编程深度解析:内存模型与对象生命周期

在实际开发中,我发现通过平台的一键部署功能,可以快速对比不同优化策略的效果,大大提高了开发效率。无论是分析对象内存布局还是测试GC性能,都能在几分钟内获得直观的结果,这对于理解C到Java的转型要点非常有帮助。内存访问模式的性能差异在实际应用中非常明显。测试数据显示,在矩阵乘法等计算密集型任务中,C语言配合AVX512指令集可以获得最佳性能,而Java的向量API也能提供接近原生代码的性能表现。Java的受检异常机制强制开发者处理可能的错误情况,这比C语言的错误码检查更加结构化,但同时也增加了代码复杂度。

SapphireFox89的博客 571

UNet 改进(19):与ASPP结合的图像分割模型

这个代码实现了一个改进版的UNet模型,在传统的UNet架构基础上,引入了ASPP模块来增强模型捕获多尺度上下文信息的能力。​​UNet主干网络​​:经典的编码器-解码器结构,带有跳跃连接​​ASPP模块​​:位于瓶颈层,用于提取多尺度特征。

2401_82355416的博客 878

JVM之对象的内存模型、创建过程、对象引用、生命周期

了解学习在JVM虚拟机中,对象的内存模型是怎样设计的、对象的创建过程是怎样的、对象的引用关系、对象的命周期以及对象的回收等。

积跬步,至千里。 1278

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

深入理解Java内存模型JVM如何管理你的对象生命周期

# 深入理解Java内存模型:JVM如何管理你的对象生命周期Java虚拟机(JVM)作为Java程序的运行环境,其内存管理机制尤其是对象生命周期的管理,是Java开发者必须掌握的核心知识。在回收前,若对象重写了finalize()方法,则有机会在GC时执行一次终结操作,但该方法不确定性大,不推荐依赖。直接指针则使引用直接指向对象地址,对象头中包含类型数据指针。建议避免频繁创建短命对象以减少GC压力,谨慎使用finalize()方法,及时解除无用对象引用(如设null),并根据应用特性选择合适的GC算法。

f3051709的博客 258

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

图解JVM内存模型:从对象分配到GC Roots的完整生命周期

本文通过图解方式,生动解析了JVM内存模型中对象从Eden区分配到晋升老年代的完整生命周期,并深入阐述了GC Roots如何通过可达性分析算法构建决定对象生死的引用链。文章涵盖了分代收集、垃圾收集器选择及元空间演进等核心机制,为Java开发者理解内存管理和性能调优提供了清晰的认知框架。

java5的博客 779

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Java的内存模型和生命周期_从一个Java对象看JVM内存模型及对象生命周期

从一个Java对象看JVM内存模型及对象生命周期从一个Java对象看JVM内存模型及对象生命周期【JVM系列4】new Object()到底占用几个字节,看完这篇就彻底明白了package com.zwx.jvm;public class HeapMemory {private Object obj1 = new Object();public static void main(String[] ...

weixin_35823441的博客 124

C++进阶:深入对象生命周期、内存模型与并发编程核心机制

在C++编程中,理解对象生命周期与内存模型是构建健壮、高效软件的基础。对象从构造到析构的完整过程,包括拷贝与移动语义的精确时序,直接影响程序的正确性与性能。内存对齐机制则关乎CPU访问效率,通过`alignas`和`alignof`可以优化数据结构布局以提升计算性能。这些底层原理支撑着现代C++的高效资源管理,例如智能指针的自动内存管理和RAII(资源获取即初始化)模式。在多线程并发场景下,`std::atomic`与内存序(`std::memory_order`)共同保障了数据同步的可见性与顺序性,是无锁

weixin_30410119的博客 256

JVM 运行时数据区详解:内存模型与对象生命周期全景解析

本文深入解析JVM运行时数据区的核心架构与运行机制,主要内容包括: JVM内存全景:详细划分线程私有区(程序计数器、Java栈、本地方法栈)和共享区(堆、方法区、常量池),通过图表对比各区域特性和配置参数 对象生命周期:完整展示从Eden区创建到老年代晋升的流程,包含逃逸分析、内存分配策略及GC回收过程的可视化说明 关键机制解析: 字符串常量池的驻留原理 元空间与永久代的本质区别 栈帧结构与方法调用的内在联系 实战指南: 内存异常分类与诊断方法 推荐工具链(jmap/jvisualvm/MAT) 生产环境配

qq_43414012的博客 1136

对象生命周期与内存模型(转载)

内存模型是随着越来越丰富和复杂的对象生命周期要求的发展而发展起来的。最初的内存模型完全是线性的,静态的,一个程序运行时所有需要的对象都是在运行前完全准备好了的,运行完了时释放掉。典型的代表就是Fortran语言。这种语言的运行性能非常高(当然了,没有任何别的消耗嘛),但是表达能力受到限制(毕竟,要求静态的确定一切对象和内存的绑定关系)。最明显的一个限制就是没办法支持递归。这种内存模型支持的对象的...

weixin_30399797的博客 71

python | Python内存模型:对象创建与销毁的生命周期

Python作为一种高级编程语言,为开发者提供了自动内存管理机制,使开发者能够专注于业务逻辑而无需手动管理内存分配和释放。Python的内存管理系统主要由内存分配器和垃圾回收器两部分组成,它们共同协作,确保程序内存使用的高效性和安全性。

csdn_xmj的博客 1089

Java的内存模型和生命周期_深入理解Java内存模型和Java对象

运行时数据区域Java虚拟机在执行Java程序时会把它所管理的内存划分为多个不同的区域,这些区域的用途和生命周期都不相同。大概如下图:分别介绍下各个数据区域存在的意义以及在JVM内存管理中承担的作用.虚拟机栈虚拟机栈是线程私有的,而且它的生命周期和线程相同.虚拟机栈是描述Java方法执行的内存模型。每个方法在执行时都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接和方法出口信息等,这里主要了...

weixin_42332144的博客 218

OO编程思想之一---对象生命周期与内存模型

内存模型基础==================================================== 内存模型是随着越来越丰富和复杂的对象生命周期要求的发展而发展起来的。 最初的内存模型完全是线性的,静态的,一个程序运行时所有需要的对象都是在运行前完全准备好了的,运行完了时释放掉。典型的代表就是Fortran语言。这种语言的运行性能非常高(当然了,没有任何别的消耗嘛),

天行健,君子以自强不息 1287
上一篇: 契约、并行和异常
下一篇: 语言的一些思考
lifeNet
博客等级 码龄20年 1粉丝 0原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值