SWIG 结构成员被 Java 的垃圾收集器过早释放
我有一个 C++ 库,Java 通过基于 SWIG 的接口调用它。在 Java 方面,我使用默认的 struct 接口和 carrays.i
的 %array_class
构建了一个包含指向其他结构数组的指针的结构。
由于 Java 的垃圾收集器不知道顶级结构的成员,因此有时会释放数组,此时其终结器将删除其后备内存。我需要一种解决方法,最好不要在 Java 中复制该结构,因为它相当大。
一个最小的示例如下所示(尽管它可能不会触发错误,因为它没有做太多事情):
C++/SWIG:
%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);
}
}
I have a C++ library that is called by Java through a SWIG-based interface. On the Java side, I build up a structure containing pointers to arrays of other structures, using the default struct interface and carrays.i
's %array_class
.
Because Java's garbage collector is not aware of the members of the top-level struct, the array is sometimes freed, whereon its finalizer delete[]
s its backing memory. I need a way around this, preferably without duplicating the struct in Java, since it's rather large.
A minimal example looks like this (although it probably won't trigger the bug since it doesn't do much):
C++/SWIG:
%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);
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
对此有几种可能的解决方案。最简单的方法是包装一个可以创建对象而无需 Java“拥有”内存的函数。这可能看起来像:
您实际上可以在创建后修改
swigCMemOwn
boolean
。类型映射应该能够将其注入到适当的位置(当将object
传递给setitem
时)。例如,您可以编写:这需要在第一次看到
object
类之前,并允许您编写类似以下内容:而不是
os.setitem(i, o);
。此主题的一个变体是使用
javain
类型映射来替换 Java 代理中的默认setitem
实现,以便它调用上的函数(您提供) >object
更改所有权,例如:在
%include "carrays.i"
之前以及通过%typemap(javacode) 相应的
。 (disown()
)对象swigCMemOwn
受保护
,因此objectArray
无法直接修改它)。还有其他可能的方法,其中也涉及设置所有权。我所展示的那些是我认为最简单的。
或者,另一种常见的解决方法是 保留对 Java 代理对象的引用,通过将其分配给成员变量。在这种情况下,因为您可能有很多对象,但它们本身必须是容器。
There's a couple of possible solutions to this. The simplest is to wrap a function that can create
object
s without Java "owning" the memory. This might look something like:You can actually modify the
swigCMemOwn
boolean
after creation. A typemap should be able to inject this at the appropriate place (when theobject
is handed tosetitem
). For example you could write:This needs to be before the
object
class is first seen and allows you to write something like:instead of
os.setitem(i, o);
.A variation on this theme would be to use a
javain
typemap to replace the defaultsetitem
implementation in the Java proxy such that it calls a function (you supply) on theobject
to change the ownership, e.g.:before the
%include "carrays.i"
and a correspondingdisown()
via%typemap(javacode) object
. (swigCMemOwn
isprotected
, so theobjectArray
can't modify that directly).There are other approaches possible too, which involve setting the ownership also. The ones I've shown are the easiest I think though.
Alternatively, another common work around would be to keep a reference to the Java proxy Object hanging around, by assigning it to a member variable. In this instance since you potentially have lots of objects that would have to be a container itself though.