【问题标题】:Android NDK - using AssetManager in native codeAndroid NDK - 在本机代码中使用 AssetManager
【发布时间】:2012-06-21 15:40:37
【问题描述】:

我需要在 C/C++ 代码中处理我的资产文件夹中的资产。像这样缓存指向 AAssetManager 的指针是否安全...:

AAssetManager* assetMgr = NULL; 

void Java_com_example_createAssetManager(JNIEnv* env, jclass clazz, jobject assetManager)
{
  AAssetManager* mgr = AAssetManager_fromJava(env, assetManager);
  assert(NULL != mgr);
  assetMgr = mgr;    
}

...然后在我需要的时候使用它? createAssetManager 是从主 Activity(UI 线程)的 Java onCreate 方法调用的,但在 C/C++ 中的用法是在 GLSurfaceView 实现中原生处理从本机方法调用的渲染和游戏滴答时。

1) 在整个应用程序生命周期内,assetMgr 指针会指向有效对象吗?在 Java 端(在 Activity 类中)像静态变量一样创建它是否足以让垃圾收集器不会破坏它?

2) 我会遇到线程问题吗?

谢谢,汤姆原子

【问题讨论】:

  • 为了安全起见,不要缓存。 AAssetManager_fromJava() 非常快。
  • 感谢您的回复。我想缓存它的原因是我不知道如何在方法调用中没有“jobject assetManager”的情况下获取指针。那么,我是否必须将此参数添加到从 Java 到 C/C++ 的每个刻度调用中,以防万一我在刻度期间需要它?或者有什么方法可以让我在需要时及时查询 Java 对象(向 Java 询问 AssetManager,然后调用 AAssetManager_fromJava,然后使用它...)

标签: android thread-safety android-assets android-ndk


【解决方案1】:

缓存资产管理器的一种稍微安全一点的方法是在 C 端保存对底层 Java 对象的全局引用以及缓存的 AAssetManager 指针。至少你会知道 C 对象后面/周围的 Java 对象不会被垃圾收集。

为此,请致电env->NewGlobalRef(assetManager)

恕我直言,跨线程边界访问资产管理器将是相当疯狂的。这是一个非常严格的设计约束 - 除非明确记录,否则在默认情况下永远不能假定线程安全。

【讨论】:

  • 对于它的价值,AAssetManager 的文档明确指出可以在多个线程之间共享本机 AAssetManager 句柄。查看source code 有一个互斥锁和一条评论说它是线程安全的。
【解决方案2】:

我编写了一个 NDK 模块 Assetbridge,您可能会觉得它很有用。它将项目 assets/ 文件夹(文件和目录)的内容导出到临时目录,然后将环境变量设置为该路径,因此您的本机代码可以 chdir() 到临时目录,您可以使用常规的旧标准库文件 IO 例程。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-27
    相关资源
    最近更新 更多