.Net 二进制反序列化运行时平台的故障检测/取证
我正在寻找有关如何检测运行时平台以公开 Microsoft .Net 二进制反序列化失败的源类型的见解。
当使用 BinaryFormatter.Deserialize(StreamingContextStates.CrossMachine) 且其中一种类型在当前二进制文件中不存在时; .Net 不会抛出错误,而是插入对象 [TypeLoadExceptionHolder]
。特别是对于集合而言,这不会立即造成问题。
随后,当集合被序列化以在应用程序层之间传输时;平台收到“序列化失败”,因为[TypeLoadExceptionHolder]
无法序列化。因此,产生的错误对于实际提供有关导致问题的源类型的线索是无用的。现在,我们正在寻找(时间很糟糕),看看哪个开发人员(数百个)向百万行平台添加了新类型。
由于用于支持平台会话缓存的序列化流,此问题经常发生。代码的部署相当频繁且以增量方式进行。在部署窗口期间,客户页面请求可以在新旧版本的代码库之间切换。不小心引入新类型将导致旧版本的页面请求崩溃。
任何关于提供运行时丰富的错误/陷阱的想法将不胜感激。
(SerializationException)
Type 'System.Runtime.Serialization.TypeLoadExceptionHolder' in Assembly 'mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' is not marked as serializable.
- at System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType type)
- at System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type type, StreamingContext context)
- at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo()
- at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter)
- at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter)
- at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo)
- at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)
- at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck)
I'm looking for insight on how to instrument a runtime platform to expose the source type of a Microsoft .Net binary deserialization failure.
When using BinaryFormatter.Deserialize(StreamingContextStates.CrossMachine)
and one of the types does not exist in the current binaries; instead of throwing an error, .Net inserts the object [TypeLoadExceptionHolder]
. Particularly for collections, this causes no immediate problem.
Subsequently when the collection is serialized for transmission between application tiers; the platform receives a 'serialization failure' because [TypeLoadExceptionHolder]
cannot be serialized. So the resulting error is useless for actually providing clues as to the source-type that caused the problem. Now the hunt (time suck) is on to see which developer (of hundreds) added a new type to a million-line platform.
This problem happens with some frequency because of the serialization stream used to support the platform sessioncache. Code is deployed fairly often and in an incremental fashion. Customer page-requests can bounce between old and new versions of the codebase during the deployment window. Careless introduction of a new type will cause the page-requests on the old version to blow up.
Any thoughts about providing runtime rich error/trap would be appreciated.
(SerializationException)
Type 'System.Runtime.Serialization.TypeLoadExceptionHolder' in Assembly 'mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' is not marked as serializable.
- at System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType type)
- at System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type type, StreamingContext context)
- at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo()
- at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter)
- at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter)
- at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Write(WriteObjectInfo objectInfo, NameInfo memberNameInfo, NameInfo typeNameInfo)
- at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)
- at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
那么,您可以采取的一种方法是使用自定义 < code>SerializationBinder 覆盖
BindToType
并在反序列化期间检查类型名称。根据您想要完成的任务,当您识别未知类型时,您可以:
引发异常(悲观):尽早发现问题,并可以使用自定义消息或异常轻松识别类型。
记录类型名称(乐观):如果存在未知类型正常的情况,日志记录将提供诊断异常(如果稍后在序列化过程中发生)所需的详细信息。
您还可以根据类型名称的特征(即,该类型是否是您的应用程序的一部分或第三方库的一部分)选择不同的方法。
反序列化期间创建的
TypeLoadExceptionHolder
实例确实包含一个非公共成员TypeName
,其中包含无法解析的类型的名称。但是,该实例无法从您稍后遇到的SerializationException
中获得,即使如此,该值也只能通过受信任上下文中的反射来获得。Well, one approach you could take is to use a custom
SerializationBinder
that overridesBindToType
and checks the type name during deserialization.Depending on what you'd like to accomplish, when you identify an unknown type you could either:
Raise an Exception (Pessimistic): Catch the issue early on and can easily identity the type with a custom message or exception.
Log the Type Name (Optimistic): If there are scenarios where unknown types are OK, logging would provide the details necessary to diagnose exceptions if they occur later during serialization.
You could also select a different approach depending on characteristics of the type name (i.e. if the type appears to be part of your application or part of a 3rd party library).
The
TypeLoadExceptionHolder
instance created during deserialization does contain a non-public memberTypeName
that contains the name of the type that could not be resolved. However, the instance is not available from theSerializationException
you encounter later on, and even so, the value would only be available via reflection in trusted contexts.