我有一种情况,我用Java与C ++代码(Android - JNI / NDK)连接 正如下面的代码注释中所解释的,我正在尝试阻止对AssetManager实例进行垃圾回收(因为我在本机代码中使用了此实例)。
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public class AndroidLauncher extends AndroidApplication implements DroidBlaster {
// We need a reference to AssetManager (used by DroidBlaster JNI/NDK),
// in order to ensure that the AssetManager instance which is passed to
// native method DroidBlaster::create, is not garbage collected while
// the native object is in use. Furthermore we pass an instance of
// AndroidLauncher (this) to the Flm::initialize method, in order to
// ensure this class is not garbage collected.
private AssetManager assetManager;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
AssetManager assetManager = getAssets();
initialize(new Flm(App.Type.PRO, this), config);
}
// ...
// ....
}
现在,Flm类(由上面的代码中的initialize方法实例化的那个)包含一个静态DroidBlaster成员(它具有由AndroidLauncher类实现的接口),它在构造函数中初始化。
public class Flm extends Game {
static DroidBlaster droidblaster;
public Flm(App.Type aAppType, final DroidBlaster droidblaster) {
super();
App.instance.setType(aAppType);
this.droidblaster = droidblaster;
}
// ...
// ....
}
我很怀疑,这个实现是否正确以确保在Flm实例存在期间,AndroidLauncher的AssetManager成员永远不会被垃圾收集?
答案 0 :(得分:2)
如果要使用本机代码中的对象,则需要对其进行本地或全局JNI引用。将对象传递给本机方法,或者从具有JNI调用的字段中提取对象,会创建本地引用。当有问题的线程返回VM时,它们将过期并被丢弃。
如果您希望引用在对本机代码的调用中继续有效,则需要使用AddDays
创建全局引用。这些不会过期,必须在不再需要时明确删除。
尝试使用Java编写的代码保留对象并没有多大意义。如果该对象尚未对本机代码可见,那么它是否被收集并不重要 - 显然没有任何内容可以引用它。如果对象对本机代码可见,并且不得丢弃,则应从本机代码创建全局引用。
有关其他信息,请参阅JNI Tips。