dotnet 使用 FormatterServices 的 GetUninitializedObject 方法在丢失 DLL 情况下能否执行
在 dotnet 里面,可以使用 FormatterServices 的 GetUninitializedObject 方法可以实现只创建对象,而不调用对象的构造函数方法。而如果在使用此方法时,存在了 DLL 缺失的情况,此时能否让此方法运行通过,创建出空的对象
答案是可以创建成功,也可以创建不成功。当所有碰到的字段都是引用类型的时候,可以创建成功。如果存在值类型,但是值类型的 DLL 定义文件被删除,将会失败
下面来写一点测试的逻辑,如下面代码分别定义 F1 和 F2 和 F3 三个不同的类型
class F1
{
public F2 F2 { get; } = new F2();
}
class F2
{
public F3 F3 { get; } = new F3();
}
public class F3
{
}
在 Main 函数里面使用下面代码调用 FormatterServices 的 GetUninitializedObject 方法创建对象
class Program
{
static void Main(string[] args)
{
var f1 = FormatterServices.GetUninitializedObject(typeof(F1));
}
}
接着将 F3 类放在另一个项目里面,然后让此项目引用包含 F3 类的项目。在构建完成之后,删除包含 F3 类的项目的输出 DLL 文件。接着运行 Main 方法,可以看到实际上 f1 对象还是被创建才出来,不会炸掉
可以通过如下方式获取本文的源代码,先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码
git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 2f00793486fcb1962de7e368ec527cf1169db135
以上使用的是 gitee 的源,如果 gitee 不能访问,请替换为 github 的源
git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
获取代码之后,进入 JinaldalurhaBelnallbune 文件夹
其实此时即使获取 F2 的类型,通过反射拿到所有的成员,也是可以获取到的,如下图
可以看到原本是 F3 的类型对应的属性,在反射拿到的是 System.Reflection.RuntimePropertyInfo
类型
可以看到对应的模块被删除时,只会提示说文件找不到,而不会让反射失败
接下来试试使用结构体的方式,也就是字段实际是值类型的方式,修改 F2 和 F3 从引用类型修改为结构体,代码如下
struct F2
{
public F3 F3 { get; }
}
public struct F3
{
static F3()
{
}
}
依然将 F3 放在另一个程序集,然后在输出文件里面删除此程序集的 DLL 文件。尝试运行代码,可以看到此时运行将会失败
原因是因为值类型需要计算对象的占用的内存空间的大小,在准备创建 F1 的时候需要开始计算 F2 的占用空间,因为 F2 是一个结构体。但是 F2 里面引用了 F3 类型,此时 F2 就需要开始计算 F3 的空间,然而定义 F3 占用空间大小的数据放在了被删除的程序集里面,因此拿不到 F3 的占用空间大小,从而计算不出 F2 的空间大小,也就无法创建 F1 对象,因此失败
那为什么 F3 的占用空间大小需要放在定义 F3 的程序集里面,不能放在被引用的如 F2 所在的程序集里面?原因在于 dotnet 的应用可以支持 DLL 兼容更新,如我可以方便的更改 F3 类型的定义,如添加一个字段。那么此时 F3 的占用内存空间大小自然就需要修改了。然而此时我可以做到不更改 F2 所在的程序集,只需要更新 F3 所在的程序集即可,这就是因为在运行时里面读取了 F3 所在的程序集拿到了 F3 的占用内存空间的大小,不需要依赖在 F2 所在的程序集的定义
可以通过如下方式获取本文的源代码,先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码
git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 415664a5516c778db662dd519e9114a320a4d690
以上使用的是 gitee 的源,如果 gitee 不能访问,请替换为 github 的源
git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
获取代码之后,进入 JinaldalurhaBelnallbune 文件夹
如果不是直接的引用的类型找不到定义的程序集,那依然可以成功,将 F2 从结构体修改为引用类型,如下面代码
class F2
{
public F3 F3 { get; }
}
此时删除 F3 所在的程序集,依然可以创建出来 F1 对象
通过上文可以了解到 F1 对象的内存空间,可以计算出来,因为 F2 是引用类型,引用类型占用的字段内存空间是固定的。所以就不需要再去计算 F2 里面包含的 F3 结构体的占用空间
当然,依然让 F2 是结构体类型,但是将 F3 修改为引用类型,也能创建成功。原因是 F2 结构体在不知道 F3 的程序集时依然可以根据引用类型占用的字段空间是固定的,计算出包含 F3 的属性的字段占用的内存,因此不需要去读取 F3 所在的程序集
通过上文可以了解到 dotnet 里面加载程序集的机制
dotnet 使用 FormatterServices 的 GetUninitializedObject 方法在丢失 DLL 情况下能否执行的更多相关文章
- delphi中的ClientDataSet组件的open和Execute方法各自在什么情况下用?
ClientDataSet组件本来是给midas用的,也是所谓的borland的三层数据技术,使用这个控件必须发行midas.dll挺麻烦的 open是通过应用的SQL语句为SELECTexecute ...
- Linux在丢失的情况下重置密码
1.开机菜单是 移动光标到第一行 --敲击e 2.找到UTF-8,加上空格rd.break,敲击ctrl+x 3.输入以下命令 mount -o remount,rw /sysroot chroot ...
- DotNet生成随机数的一些方法
在项目开发中,一般都会使用到“随机数”,但是在DotNet中的随机数并非真正的随机数,可在一些情况下生成重复的数字,现在总结一下在项目中生成随机数的方法. 1.随机布尔值: /// <summa ...
- ASP.NET Session丢失的情况
正常操作情况下会有ASP.NET Session丢失的情况出现.因为程序是在不停的被操作,排除Session超时的可能.另外,Session超时时间被设定成60分钟,不会这么快就超时的. 现在我就把原 ...
- 在没备份undo的情况下,undo丢失,重启数据库报ORA-01157错误
今天做了一下undo隐藏参数的实验 在没有备份的情况下,删除正在使用的undo,然后关机 (本次使用的的oracle的隐藏参数,慎用!!!!!!!!!!!!!!) idle> select * ...
- 后端把Long类型的数据传给前端,前端可能会出现精度丢失的情况,以及解决方案
后端把Long类型的数据传给前端,前端可能会出现精度丢失的情况.例如:201511200001725439这样一个Long类型的整数,传给前端后会变成201511200001725440. 解决方法: ...
- RabbitMQ-如何保证消息在99.99%的情况下不丢失
1. 简介 MQ虽然帮我们解决了很多问题,但是也带来了很多问题,其中最麻烦的就是,如何保证消息的可靠性传输. 我们在聊如何保证消息的可靠性传输之前,先考虑下哪些情况下会出现消息丢失的情况. 首先,上图 ...
- 什么情况下才要重写Objective-C中的description方法
特别注意: 千万不要在description方法中同时使用%@和self,同时使用了%@和self,代表要调用self的description方法,因此最终会导致程序陷入死循环,循环调用descrip ...
- 如何让ASP.NET Web API的Action方法在希望的Culture下执行
在今天编辑推荐的<Hello Web API系列教程--Web API与国际化>一文中,作者通过自定义的HttpMessageHandler的方式根据请求的Accep-Language报头 ...
- 关于在gridview中有dorpdownlist的情况下使用自带编辑模板的方法
今天记录一下在gridview中,如果有dropdownlist的情况下使用gridview自带编辑模式的方法. 好吧,今天的这个问题有点绕,详细解释一下目的. 因为gridview中的某些列的数据是 ...
随机推荐
- 一文搞懂idea中的根目录和路径(以Mybatis为例)
一文搞懂idea中的根目录和路径(以Mybatis为例) 在 IntelliJ IDEA 中,项目结构和组织比较灵活,允许用户根据项目需求进行定制. 1.根目录概念: 1.1 项目根目录(Projec ...
- FreeRTOS教程10 低功耗
1.准备材料 正点原子stm32f407探索者开发板V2.4 STM32CubeMX软件(Version 6.10.0) Keil µVision5 IDE(MDK-Arm) 野火DAP仿真器 XCO ...
- Rust使用Sauron实现Web界面交互
目录 简介 架构 Application 和组件 简单入门示例 先决条件 创建新项目 编译库文件 引用库文件 运行项目 界面交互示例 创建项目 编译库文件 引用库文件 引用库文件 运行项目 参考资料 ...
- 使用systemd部署r-nacos
1. 前言 r-nacos是一个用rust实现的nacos服务.相较于java nacos来说,是一个提供相同功能,启动更快.占用系统资源更小(初始内存小于10M).性能更高.运行更稳定的服务. r- ...
- Elasticsearch内核解析 - 数据模型篇【转载】
原文链接 Elasticsearch是一个实时的分布式搜索和分析引擎,它可以帮助我们用很快的速度去处理大规模数据,可以用于全文检索.结构化检索.推荐.分析以及统计聚合等多种场景. Elasticsea ...
- ftp安装与配置 云服务器 CentOS7
1.FTP的安装 #安装 yum install -y vsftpd #设置开机启动 systemctl enable vsftpd.service #启动 systemctl start vsftp ...
- FastJson反序列化1-FastJson基础使用及反序列化流程分析
1.FastJson简介及使用 fastjson是阿里巴巴的开源JSON解析库,它可以解析JSON格式的字符串,支持将Java Bean序列化为JSON字符串,也可以从JSON字符串反序列化到Java ...
- DGC:真动态分组卷积,可能是解决分组特征阻塞的最好方案 | ECCV 2020 Spotlight
近期,动态网络在加速推理这方面有很多研究,DGC(Dynamic Group Convolution)将动态网络的思想结合到分组卷积中,使得分组卷积在轻量化的同时能够加强表达能力,整体思路直接清晰,可 ...
- 利用 🤗 Optimum Intel 和 fastRAG 在 CPU 上优化文本嵌入
嵌入模型在很多场合都有广泛应用,如检索.重排.聚类以及分类.近年来,研究界在嵌入模型领域取得了很大的进展,这些进展大大提高了基于语义的应用的竞争力.BGE.GTE 以及 E5 等模型在 MTEB 基准 ...
- BIO ,NIO ,AIO
一.同步阻塞I/O(BIO): 服务器实现模式: 一个连接一个线程,即客户端有连接请求时服务器就需要启动一个线程进行处理 弊端:如果这个连接不做任何事情会造成不必要的线程开销 解决措施:可以通过线程池 ...