2

一旦我将一个方法存储在 V8::Context 中,该方法的所有后续实例都以任何名称存储在任何上下文中,其行为就像初始实例一样(即,就好像再次存储了原始实例一样)。

我试图通过以下方式隔离/证明问题:

require 'V8'

class TestClass
  def test_method
    self.inspect
  end
end

(1..2).each do |cxt_i|
  cxt = V8::Context.new
  [:test_method, :test_method2].each_with_index do |method_name, method_i|
    method = TestClass.new.method(:test_method)
    cxt[method_name.to_s] = method
    script = method_name.to_s+'()'
    puts "Context #{cxt_i}, method #{method_i+1} result is #{method.call}, V8 returns #{cxt.eval(script)}"
  end
end

产生以下输出:

Context 1, method 1 result is #<TestClass:0x007fce2419cdb0>, V8 returns #<TestClass:0x007fce2419cdb0>
Context 1, method 2 result is #<TestClass:0x007fce2419b780>, V8 returns #<TestClass:0x007fce2419cdb0>
Context 2, method 1 result is #<TestClass:0x007fce2419abc8>, V8 returns #<TestClass:0x007fce2419cdb0>
Context 2, method 2 result is #<TestClass:0x007fce24199a98>, V8 returns #<TestClass:0x007fce2419cdb0>
4

1 回答 1

1

这是一个弱参考问题。GC.start通过在内部循环中插入 a ,我们强制 V8 上下文中的弱引用被垃圾回收。不过,它会大大减慢它的速度。

require 'v8'

class TestClass
  def test_method
    self.inspect
  end
end

(1..2).each do |cxt_i|
  cxt = V8::Context.new
  [:test_method, :test_method2].each_with_index do |method_name, method_i|
    method = TestClass.new.method(:test_method)
    cxt[method_name.to_s] = method
    script = method_name.to_s+'()'
    puts "Context #{cxt_i}, method #{method_i+1} result is #{method.call}, V8 returns #{cxt.eval(script)}"
    GC.start # <<<<=========
  end
end

输出:

Context 1, method 1 result is #<TestClass:0x007f8f13a26cd8>, V8 returns #<TestClass:0x007f8f13a26cd8>
Context 1, method 2 result is #<TestClass:0x007f8f135cca48>, V8 returns #<TestClass:0x007f8f135cca48>
Context 2, method 1 result is #<TestClass:0x007f8f135ceac8>, V8 returns #<TestClass:0x007f8f135ceac8>
Context 2, method 2 result is #<TestClass:0x007f8f135cdbf0>, V8 returns #<TestClass:0x007f8f135cdbf0>

ruby -v 是ruby 2.0.0p195 (2013-05-14 revision 40734) [x86_64-linux],libv8 是3.11.8.17 x86_64-linux

于 2013-06-25T07:28:39.913 回答