HandleScope 和 LocalReferenceTable 的区别

部署运行你感兴趣的模型镜像

在 ART(Android Runtime)虚拟机中,HandleScope 和 LocalReferenceTable 都是用于管理 JNI(Java Native Interface)引用的重要机制。

1. HandleScope

作用:

HandleScope 是一个基于栈的对象引用管理机制,用于管理局部引用(local references)。它将 Java 对象(jobject)存储在栈上,并自动处理这些引用的生命周期。

特点:
  • 基于栈HandleScope 是在栈上分配的,因此它的生命周期受限于当前函数的执行范围。当函数返回时,HandleScope 会自动析构,并释放其中存储的对象引用。
  • 自动管理生命周期:由于它是基于栈的,当作用域完毕,HandleScope 会自动销毁,不需要手动释放引用的内存。
  • 高效:因为是在栈上操作,通常比堆分配的局部引用(如 env->NewLocalRef)更高效。
  • 适用于短生命周期的引用:通常用于那些只在函数内部使用,并且生命周期不超过函数执行范围的对象引用。
示例代码:
void ExampleFunction(JNIEnv* env, jobject obj) {
    StackHandleScope<jobject> hs(env);
    jobject managed_obj = hs.NewHandle(obj);
    
    // 使用 managed_obj
}

在上面的代码中,managed_obj 是一个在 StackHandleScope 中创建的句柄,它的生命周期由 StackHandleScope 管理,当函数执行完毕,StackHandleScope 析构,managed_obj 也自动失效。

2. LocalReferenceTable

作用:

LocalReferenceTable 是 ART 虚拟机中用于管理局部引用表的结构。它是一个更底层的机制,用于存储和管理所有通过 JNI 环境(JNIEnv)创建的局部引用。

特点:
  • 堆上管理LocalReferenceTable 是在堆上分配的,用于存储通过 NewLocalRefFindClassNewObject 等 JNI 函数创建的局部引用。
  • //分配代码
    LrtEntry* SmallLrtAllocator::Allocate(size_t size, std::string* error_msg) {
      size_t index = GetIndex(size);
      MutexLock lock(Thread::Current(), lock_);
      size_t fill_from = index;
      while (fill_from != num_lrt_slots_ && free_lists_[fill_from] == nullptr) {
        ++fill_from;
      }
      void* result = nullptr;
      if (fill_from != num_lrt_slots_) {
        // We found a slot with enough memory.
        result = free_lists_[fill_from];
        free_lists_[fill_from] = *reinterpret_cast<void**>(result);
      } else {
        // We need to allocate a new page and split it into smaller pieces.
        MemMap map = NewLRTMap(gPageSize, error_msg);
        if (!map.IsValid()) {
          return nullptr;
        }
        result = map.Begin();
        shared_lrt_maps_.emplace_back(std::move(map));
      }
      while (fill_from != index) {
        --fill_from;
        // Store the second half of the current buffer in appropriate free list slot.
        void* mid = reinterpret_cast<uint8_t*>(result) + (kInitialLrtBytes << fill_from);
        DCHECK(free_lists_[fill_from] == nullptr);
        *reinterpret_cast<void**>(mid) = nullptr;
        free_lists_[fill_from] = mid;
      }
      // Clear the memory we return to the caller.
      std::memset(result, 0, kInitialLrtBytes << index);
      return reinterpret_cast<LrtEntry*>(result);
    }

  • 手动管理生命周期:局部引用通过 LocalReferenceTable 管理,开发者可以手动调用 DeleteLocalRef 来释放这些引用或者作用域结束自动释放
示例代码:
void ExampleFunction(JNIEnv* env, jobject obj) {
    jobject localRef = env->NewLocalRef(obj);
    
    if (localRef != nullptr) {
        // 使用 localRef
        
        env->DeleteLocalRef(localRef);  // 手动删除局部引用
    }
}

在上面的代码中,localRef 是一个通过 NewLocalRef 创建的局部引用

区别总结

特性HandleScopeLocalReferenceTable
存储位置基于栈的对象引用管理堆上的局部引用表
生命周期管理自动管理,函数返回时自动销毁自动或手动
适用场景适用于短生命周期的对象引用,通常在函数内部使用适用于短生命周期的对象引用,通常在函数内部使用
效率更高效,因为基于栈相对较低效,在堆上分配
释放时机函数执行完毕时自动释放手动释放或者函数执行完毕时自动释放
全局管理不需要全局管理,只在当前函数范围内有效不需要全局管理,只在当前函数范围内有效

总结

HandleScope 和 LocalReferenceTable 的主要区别在于它们的管理方式和适用场景。HandleScope 在栈上分配,效率更高,空间有限,但无法删除单个引用

LocalReferenceTable 在堆上分配,空间较大但效率较低,可单独管理对象引用

您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值