java - SWIG 结构成员被 Java 的垃圾收集器过早释放

标签 java c++ garbage-collection swig finalizer

我有一个 C++ 库,它由 Java 通过基于 SWIG 的接口(interface)调用。在 Java 方面,我使用默认结构接口(interface)和 carrays.i%array_class 构建了一个包含指向其他结构数组的指针的结构。

因为 Java 的垃圾收集器不知道顶级结构的成员,数组有时被释放,其终结器 delete[] 是其后备内存。我需要一种解决方法,最好不要在 Java 中复制结构,因为它相当大。

一个最小的例子看起来像这样(尽管它可能不会触发错误,因为它做的不多):

C++/痛饮:

%module example

%include "carrays.i"
%array_class(object, objectArray);

struct object {
    unsigned int id;
    char *name;
};

struct data {
    size_t nobjects;
    object *objects;
};

void use_data(data*);

Java:

public class Example {
    private static data writeData() {
        data d = new data();
        objectArray os = new objectArray(3);
        for (int i = 0; i < 3; i++) {
            object o = new object();
            o.setId(i);
            o.setName("obj" + i);
            os.setitem(i, o);
        }
        d.setNobjects(3);
        d.setObjects(os.cast());

        return d;
    }

    public static void main(String[] args) {
        data d = writeData();
        example.use_data(d);
    }
}

最佳答案

对此有几个可能的解决方案。最简单的方法是包装一个可以创建 object 而无需 Java“拥有”内存的函数。这可能看起来像:

%inline %{
object *new_object() {
  // SWIG will assume that it doesn't own this
  return new object;
}
%}

您实际上可以在创建后修改 swigCMemOwn boolean。类型映射应该能够在适当的位置注入(inject)它(当 object 被传递给 setitem 时)。例如你可以这样写:

%typemap(javacode) object %{
  object transfer() {
    swigCMemOwn = false;
    return this;
  }
%}

这需要在 object 类首次出现之前进行,并允许您编写如下内容:

os.setitem(i, o.transfer());

代替 os.setitem(i, o);


这个主题的一个变体是使用 javain 类型映射来替换 Java 代理中的默认 setitem 实现,这样它就调用一个函数(你提供) object 更改所有权,例如:

%javamethodmodifiers objectArray::setitem "protected";
%rename  objectArray::setitem setitemImpl;

%typemap(javacode) objectArray %{
  public void setitem(int i, object o) {
    o.disown();
    setitemImpl(i, o);
  }
%}

%include "carrays.i" 和相应的 disown() 之前,通过 %typemap(javacode) 对象。 (swigCMemOwn保护,因此 objectArray 不能直接修改它)。


还有其他可能的方法,也涉及设置所有权。不过,我展示的是我认为最简单的。

或者,另一种常见的解决方法是 keep a reference to the Java proxy Object hanging around ,通过将其分配给成员变量。在这种情况下,因为您可能有很多对象,但它们本身必须是容器。

关于java - SWIG 结构成员被 Java 的垃圾收集器过早释放,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9100955/

相关文章:

java - 如何根据这个统计数据改进java代码?

java - 正常字段没有类型为 java.lang.String 的合格 bean 异常

c++ - 复制省略返回值和 noexcept

php - 过早收集资源垃圾

java - 任何人都可以在Java中共享垃圾收集器算法

javascript - 如何使用 HTMLUnit 编写事件处理程序并检测某些 JavaScript 调用?

java - 为什么java类型删除会改变目标集合的非泛型类型?

c++ - 返回 C++ 中的引号

C++奇怪的语法

java - JVM ClassUnloadingWithConcurrentMark 标志