如何正确处置和释放用于V8.Net.V8Engine实例的内存?

时间:2015-12-07 13:22:35

标签: c# .net memory memory-leaks v8.net

我在使用我的V8Engine实例时遇到了一个问题,它似乎有一个小的内存泄漏,并且处理它,以及强制垃圾收集似乎没有多大帮助。最终会在V8Enging local_m_negine = new V8Engine()声明Fatal error in heap setup, Allocation failed - process out of memoryAttempted to read or write protected memory. This is often an indication that other memory is corrupt.

上抛出AccessViolationException

通过任务管理器监控程序的内存使用情况,同时运行时确认它正在泄漏内存,我认为每隔几秒就会大约1000 KB。我怀疑正在执行的脚本中声明的变量没有被收集,或者与GlobalObject.SetProperty方法有关。致电V8Engine.ForceV8GarbageCollection()V8Engine.Dispose()甚至GC.WaitForPendingFinalizers()& GC.Collect()并没有阻止这个内存被泄露(尽管值得注意的是,这些命令到位时似乎泄漏得更慢,而且我知道我不应该使用GC,但它确实存在最后一招,看看它是否能解决这个问题。)

一个可能提供解决方案的切线问题是无法清除V8Engine的执行上下文。我需要处理并重新实例化每个脚本的引擎,我相信这是发生内存泄漏的地方,否则我遇到已经声明变量的问题,导致V8Engine.Execute()抛出一个异常,说这样

我可以肯定地确认内存泄漏与V8Engine实现有关,因为运行使用Microsoft的这个程序的旧版本.JScript没有这样的内存泄漏,并且使用的内存保持一致。

受影响的代码如下;

//Create the V8Engine and dispose when done
using (V8Engine local_m_engine = new V8Engine()) 
{
    //Set the Lookup instance as a global object so that the JS code in the V8.Net wrapper can access it
    local_m_engine.GlobalObject.SetProperty("Lookup", m_lookup, null, true, ScriptMemberSecurity.ReadOnly);
    //Execute the script
    result = local_m_engine.Execute(script);

    //Please just clear everything I can't cope.
    local_m_engine.ForceV8GarbageCollection();
    local_m_engine.GlobalObject.Dispose();
}

修改

不确定这会有多大用,但我已经在其上运行了一些内存分析工具,并且在运行原始代码的隔离版本后得知,我的软件最终会有大量的IndexedObjectList& #39;充满空值(见这里:http://imgur.com/a/bll5K)。对于每个V8Engine实例,它似乎都有每个类的一个实例,但它们不会被处置或释放。我不能帮助,但觉得我在这里错过了一个命令或什么。 我用来测试和重新创建上述实现导致的内存泄漏的代码如下:

using System;
using V8.Net;

namespace V8DotNetMemoryTest
{
    class Program
    {
        static void Main(string[] args)
        {
            string script = @"  var math1 = 5;
                                var math2 = 10;
                                result = 5 + 10;";
            Handle result;
            int i = 0;
            V8Engine local_m_engine;
            while (true)
            {
                //Create the V8Engine and dispose when done
                local_m_engine = new V8Engine();

                //Set the Lookup instance as a global object so that the JS code in the V8.Net wrapper can access it
                //local_m_engine.GlobalObject.SetProperty("Lookup", m_lookup, null, true, ScriptMemberSecurity.ReadOnly);
                //Execute the script
                result = local_m_engine.Execute(script);
                Console.WriteLine(i++);

                result.ReleaseManagedObject();
                result.Dispose();

                local_m_engine.Dispose();
                GC.WaitForPendingFinalizers();
                GC.Collect();

                local_m_engine = null;

            }
        }
    }
}

1 个答案:

答案 0 :(得分:1)

对不起,我不知道这个问题存在。确保使用v8.net标签。

您的问题是这一行:

result = local_m_engine.Execute(script);

返回的结果永远不会被丢弃。 ;)您负责返回的句柄。这些句柄是结构值,而不是类对象。

您也可以执行using (result = local_m_engine.Execute(script)) { ... }

有一个new version released。我最终将再次恢复该项目,因为FlowScript VPL项目将需要它-它现在也支持.Net Standard和跨平台支持!