SWIG / Java:对象过早得到GCed

时间:2016-03-30 17:56:10

标签: java c++ swig

我正在使用SWIG围绕某些C ++代码编写Java包装器。绑定现在正在运行,但不幸的是,在本机端创建的对象是免费的,而且速度太快。

自下而上的代码:

C ++: GitHub

namespace lm::ngram {
    // ...
    lm::base::Model* LoadVirtual(const char *file_name,
                                 const lm::ngram::Config &config = lm::ngram::Config());
}

SWIG: GitHub

public class Model {
    private com.github.jbaiter.kenlm.jni.Model cModel;
    private String path;
    //...
    public Model(String path, Config config) throws ModelException {
        this.path = path;
        this.cModel = KenLM.LoadVirtual(path, config.getCConfig());
    }

    public long getOrder() {
        return this.cModel.Order();
    }
    //...
}

Java: GitHub

@Test
public void getOrder() throws Exception {
    Model model = new Model(toy0Url.getPath());
    assertEquals(model.getOrder(), 3);
}

有问题的测试用例GitHub

NullPointerException

由于model.cModelnull,测试失败并引发Model。但是,当我在getOrder构造函数中设置断点时,该字段设置正确,Model返回预期结果。但是,只要构建器的范围被删除,我的null类上的所有字段就会突然cModelnull path null可能是因为我对SWIG的内存管理缺乏了解,但{{1}}字段{{1}}也是如此令人费解对我来说。

2 个答案:

答案 0 :(得分:1)

您可能正在创建新对象以便与Java端一起使用(在本机端没有对该对象的引用)。 如果是真的,则需要指定此方法创建将遵循java lifetime / gc

的新对象
%newobject lm::base::Model* LoadVirtual(const char *file_name,
                             const lm::ngram::Config &config = lm::ngram::Config());

您可以在swig文档中找到更多相关信息:http://www.swig.org/Doc1.3/Customization.html#ownership

答案 1 :(得分:0)

根本原因实际上是我的Java代码中的一个错误,与SWIG本身无关。 我有Model类的两个构造函数,其中一个使用new Model(args)而不是this(args)调用另一个。当然,这会立即丢弃正确初始化的实例,并留下未初始化的对象(所有内容都为null)。