代码之家  ›  专栏  ›  技术社区  ›  Mike Atlas

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

  •  8
  • Mike Atlas  · 技术社区  · 14 年前

    OutOfMemoryException ,对于非常简短和简单的XML snippits(例如。, <ABC def='123'/> ):

    public static T DeserializeXmlNode<T>(XmlNode node)
    {
        try
        {
            return (T)new XmlSerializer(typeof(T))
                .Deserialize(new XmlNodeReader(node));
        }
        catch (Exception ex)
        {
            throw; // just for catching a breakpoint.
        }
    }
    

    我读了进去 this MSDN article 如果在构造函数中使用带有附加参数的XmlSerializer,每次调用它时都会生成未缓存的序列化程序集,从而导致 . 但是我没有在构造函数中使用额外的参数。在新启动的AppDomain中第一次调用它时也会发生这种情况,所以这也没有意义。

    4 回复  |  直到 14 年前
        1
  •  4
  •   Mike Atlas    13 年前

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

    最终的解决方案与反序列化问题无关。相反,它涉及到完全卸载和安装一个全新的Oracle拷贝 ODP.NET

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

    假设是一个可用的(但已损坏的)ODP.NET驱动程序有不安全的代码,并且正在重复地覆盖服务器附近受.NET保护的内存区域 Deserialize 反序列化 在任何ODP.NET调用之前被调用,它可以正常工作。但是,在使用任何ODP.NET调用之后,所有后续的反序列化调用都将失败。

    两次 在两种不同的产品中,一种是安装ODP.NET的好的/新的/干净的/新的副本。

    不漂亮。。。但这就是解决问题的方法。

        2
  •  2
  •   Community Maksym Gontar    7 年前

    here

    我已经 我找到了这个问题的解决办法。这是一个错误 .NET 3.5 SP1 .

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

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

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

    KB957543 热修复程序。

        3
  •  1
  •   chilltemp    14 年前

    你没有提供足够的细节来重现你的问题。但是,读取器实现了IDisposable,应该正确地处理它。最好把它包在一个使用块里。大多数开发人员在忘记处理某些东西时从来不会遇到问题,因为垃圾收集器最终会清理掉这些乱七八糟的东西。然而,在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);
    }
    
        4
  •  1
  •   Wallace Breza    14 年前

    基于 documentation 对于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.
    }