在这个代码示例中,是否会由JVM对AssetManager类成员进行垃圾回收?

时间:2015-09-05 13:25:35

标签: java android c++ android-ndk garbage-collection

我有一种情况,我用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成员永远不会被垃圾收集?

1 个答案:

答案 0 :(得分:2)

如果要使用本机代码中的对象,则需要对其进行本地或全局JNI引用。将对象传递给本机方法,或者从具有JNI调用的字段中提取对象,会创建本地引用。当有问题的线程返回VM时,它们将过期并被丢弃。

如果您希望引用在对本机代码的调用中继续有效,则需要使用AddDays创建全局引用。这些不会过期,必须在不再需要时明确删除。

尝试使用Java编写的代码保留对象并没有多大意义。如果该对象尚未对本机代码可见,那么它是否被收集并不重要 - 显然没有任何内容可以引用它。如果对象对本机代码可见,并且不得丢弃,则应从本机代码创建全局引用。

有关其他信息,请参阅JNI Tips