.net OutOfMemoryError调用XmlSerializer.Deserialize()-与XML大小无关!

.net OutOfMemoryError调用XmlSerializer.Deserialize()-与XML大小无关!,.net,serialization,out-of-memory,xmlserializer,.net,Serialization,Out Of Memory,Xmlserializer,这真是一只疯狂的虫子。下面为非常简短的XML片段抛出一个OutOfMemoryException(例如,如果我在构造函数中使用带有附加参数的XmlSerializer,每次调用它时都会生成未缓存的序列化程序集,从而导致程序集泄漏。但我在构造函数中没有使用附加参数。在新启动的AppDomain中第一次调用它时也会发生这种情况,因此也没有道理 给出了什么?您没有提供足够的详细信息来重新创建您的问题。但是,读取器实现IDisposable,应该正确地进行处理。最好是将其包装在using块中。大多数开发

这真是一只疯狂的虫子。下面为非常简短的XML片段抛出一个
OutOfMemoryException
(例如,
如果我在构造函数中使用带有附加参数的XmlSerializer,每次调用它时都会生成未缓存的序列化程序集,从而导致程序集泄漏。但我在构造函数中没有使用附加参数。在新启动的AppDomain中第一次调用它时也会发生这种情况,因此也没有道理


给出了什么?

您没有提供足够的详细信息来重新创建您的问题。但是,读取器实现IDisposable,应该正确地进行处理。最好是将其包装在using块中。大多数开发人员在忘记处理某件事情时不会遇到问题,因为垃圾收集器最终会清理mess、 然而,在GC开始清理之前编写导致问题的代码并不困难,甚至可以完全阻止清理

public static T DeserializeXmlNode<T>(XmlNode node)
{
    XmlSerializer xs = new XmlSerializer(typeof(T));
    using(XmlNodeReader xr = new XmlNodeReader(node))
        return (T)xs.Deserialize(xr);
}
公共静态T反序列化XmlNode(XmlNode) { XmlSerializer xs=新的XmlSerializer(typeof(T)); 使用(XmlNodeReader xr=新的XmlNodeReader(节点)) 返回(T)xs.反序列化(xr); }
根据XmlSerializer类的类型,您应该缓存XmlSerializer,否则可能会导致性能差或内存泄漏

Hashtable serializers = new Hashtable();

// Use the constructor that takes a type and XmlRootAttribute.
XmlSerializer s = new XmlSerializer(typeof(MyClass), myRoot);

// Implement a method named GenerateKey that creates unique keys 
// for each instance of the XmlSerializer. The code should take 
// into account all parameters passed to the XmlSerializer 
// constructor.
object key = GenerateKey(typeof(MyClass), myRoot);

// Check the local cache for a matching serializer.
XmlSerializer ser = (XmlSerializer)serializers[key];
if (ser == null) 
{
    ser = new XmlSerializer(typeof(MyClass), myRoot);
    // Cache the serializer.
    serializers[key] = ser;
}
else
{
    // Use the serializer to serialize, or deserialize.
}

编辑:不幸的是,这不是解决方案,但它可能会帮助其他人找到一个非常类似的问题。这个答案就是实际的解决方案。

我相信我找到了这个问题的解决办法。这是一个错误

序列化在3.5 SP1上挂起或抛出带有静态委托和ISerializable的OutOfMemoryException(ID:):

当泛型类实现ISerializable并具有使用泛型类型参数的静态委托成员时,二进制反序列化挂起(在Windows Server 2003的32位系统上)或抛出OutOfMemoryException(在Windows Server 2008的64位系统上)

此错误在.NET 3.5 SP1中发生,在没有SP1的.NET 3.5中不会发生


解决方案是安装热修复程序。

好吧,我的问题的最终答案不会帮助所有遇到这个问题的人,但是我的一些同事在几个月后也遇到了使用不同产品的不同系统。几个月后,当他们在这里找到我的帖子时,他们大笑起来,怀疑我是否真的解决了这个问题t、 因为这里不接受任何解决方案

最终的解决方案与反序列化问题无关。相反,它涉及到完全卸载并安装一个全新的Oracle数据库客户端副本,这是我们的许多应用程序(如果不是所有应用程序)使用的提供商

根据轶事证据,这个问题似乎出现在ODP.NET程序集的补丁版本不正确的情况下,这些版本随后通过虚拟机克隆传播到其他系统

当ODP.NET被完全删除,并且从Oracle网站检索并安装了一个新的兼容版本时,问题完全消失了

假设是一个可用的(但损坏的)ODP.NET驱动程序有不安全的代码,在第一次使用后会重复覆盖
反序列化
方法附近的.NET受保护内存区域。如果在任何ODP.NET调用之前调用了
反序列化
,它将正常工作。但是,在使用任何ODP.NET调用之后,所有后续的反序列化调用都将失败

最终的解决方案是安装一个好的/新鲜的/干净的/新的ODP.NET副本,这一点在两个不同的产品中已经解决了两次


不漂亮…但这就是解决问题的原因。

最有可能的候选类型似乎是您正在反序列化的类型-您可以发布破坏它的类型的代码吗?我使用xsd架构文档中的xsd.exe生成了该类。XML可能有问题。可能是某种递归在进行?该类的具体内容是什么生成异常的类型?我在反序列化时的内存不足与内存碎片有关。您分析过吗?一个简单的测试项目是否生成相同的异常?您的类是否具有调用自身的属性?这将导致递归,我以前也遇到过此问题。(但是,内存不足的情况除外。)@Mike Atlas在XSD和XML中寻找任何奇怪的东西。我认为如果没有更多信息,我们不能做更多的事情。如果可能的话,也可以发布堆栈。这肯定是我的疏忽,但这真的会在新加载的AppDomain中第一次调用它时就耗尽可用内存吗?不会。我倾向于使用它正如其他人的评论中所建议的那样,你的目标类有问题。你能发布有问题的类吗?我的OP中的MSDN链接说,像我使用的那样使用基本构造函数已经有内置缓存了。我自己第二次缓存它并不能解决我所看到的问题,因为它在第一次使用时会立即破坏堆栈-没有此时已经创建了其他序列化程序,这将填满内存。安装修复程序解决了您的问题吗?因为二进制序列化与XML序列化无关,所以我认为这个KB不会有帮助。实际上,在我兴奋的时候,我刚刚将测试机回滚到.NET 3.5平台,OOM就如我所希望的那样消失了.我想我现在需要测试修补程序本身,然后…是的,事实上,这也不是答案。我将把它留给子孙后代一段时间。
Hashtable serializers = new Hashtable();

// Use the constructor that takes a type and XmlRootAttribute.
XmlSerializer s = new XmlSerializer(typeof(MyClass), myRoot);

// Implement a method named GenerateKey that creates unique keys 
// for each instance of the XmlSerializer. The code should take 
// into account all parameters passed to the XmlSerializer 
// constructor.
object key = GenerateKey(typeof(MyClass), myRoot);

// Check the local cache for a matching serializer.
XmlSerializer ser = (XmlSerializer)serializers[key];
if (ser == null) 
{
    ser = new XmlSerializer(typeof(MyClass), myRoot);
    // Cache the serializer.
    serializers[key] = ser;
}
else
{
    // Use the serializer to serialize, or deserialize.
}