GetOracle十进制内存泄漏 [英] GetOracleDecimal Memory Leak

查看:69
本文介绍了GetOracle十进制内存泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

@GilShalit发布了t

@GilShalit posted this comment a year ago:

好吧,我们已经不信任ODP (.Net 2.0)争夺内存后 泄漏(在我们提供给 客户)在GetOracleDecimal中 一年...祝你好运!" – GilShalit Aug 09年27日在12:44

"Well, we have come to distrust ODP (.Net 2.0) after fighting a memory leak (in code we supplied to a customer) in GetOracleDecimal for over a year... Good luck!" – GilShalit Aug 27 '09 at 12:44

您是如何解决的?

我们有一项服务,每隔几分钟会查询Oracle数据库,而该服务不会释放内存.在使用WinDbg进行了一些调查之后,我发现此类型正在终结队列中堆积:Oracle.DataAccess.Types.OpoDecCtx.

We have a service that queries an Oracle database every few minutes that is not releasing memory; after some investigation using WinDbg I discovered that this type is piling up in the finalize queue: Oracle.DataAccess.Types.OpoDecCtx.

我认为这是问题所在:

decimal volume = (decimal)OracleDecimal.SetPrecision(reader.GetOracleDecimal(5), 28);

我对此进行了评论,并且内存泄漏消失了.

I commented this out and the memory leak disappeared.

任何想法都会受到赞赏-谢谢!

Any thoughts will be appreciated - thanks!

推荐答案

这是ODP.NET的一个旧问题(请参见此处:

This is an old issue with ODP.NET (see here: Memory Problems with ODP.NET 10.1.0.4 ).

OracleDecimal类型保存对名为OpoDecCtx的内部类的实例的引用. OpoDecCtx实现了IDisposable(因为它本身引用的是非托管内存),但是由于OracleDecimal没有实现IDisposable,因此您必须等待垃圾收集器运行以释放底层的非托管内存.您可以使用.NET Reflector之类的工具来检查所有这些内容.

The OracleDecimal type holds a reference to an instance of an internal class named OpoDecCtx. OpoDecCtx implements IDisposable (as it's itself referencing unmanaged memory), but since OracleDecimal does not implement IDisposable, you'll have to wait for the garbage collector to run to free the underlying unmanaged memory. You can check all this using a tool such as .NET Reflector.

尽管从技术上讲这不是物理"内存泄漏(最终将释放内存),但是当您处理大量OracleDecimal类型的实例时,这实际上是一个问题.我不知道为什么Oracle不简单地实现IDisposable,这是一件简单的事情...

Although it's not technically a "physical" memory leak (memory will be eventually freed), it is actually a problem when you're dealing with a large amount of instances of the OracleDecimal type. I don't know why Oracle does not simply implement IDisposable, it's a simple thing to do...

无论如何,我建议您使用反射自行完成一些黑客工作:

Anyway, I suggest you do some hack job yourself, using reflection:

public static class OracleExtentions
{
    public static void Dispose(this OracleDecimal od) // build an extension method
    {
        if (OracleDecimalOpoDecCtx == null)
        {
            // cache the data
            // get the underlying internal field info
            OracleDecimalOpoDecCtx = typeof(OracleDecimal).GetField("m_opoDecCtx", BindingFlags.Instance | BindingFlags.NonPublic);
        }
        IDisposable disposable = OracleDecimalOpoDecCtx.GetValue(od) as IDisposable;
        if (disposable != null)
        {
            disposable.Dispose();
        }
    }

    private static FieldInfo OracleDecimalOpoDecCtx;
}

您将像这样使用它:

OracleDecimal od = reader.GetOracleDecimal(5);
decimal volume = (decimal)OracleDecimal.SetPrecision(od, 28);
od.Dispose();

这篇关于GetOracle十进制内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆