未捕获的 Kotlin 异常:kotlin.native.In CorrectDereferenceException:非法尝试访问非共享

2024-05-14

我尝试使用 Kotlin MPP(Multiplatform) 开发 Android 和 iOS 之间的共享库。但我面临着 iOS 中线程的问题。对于我在 iOS 中的应用程序,我在主线程中建立了对象,但它可能调用其他线程中的函数并抛出此异常,如下所示:

Uncaught Kotlin exception: kotlin.native.IncorrectDereferenceException: illegal attempt to access non-shared example.api.DrivingBehaviorDetector@397cba8 from other thread
        at 0   DrivingBehaviorDetector             0x00000001037619d7 kfun:kotlin.Throwable.<init>(kotlin.String?)kotlin.Throwable + 87
        at 1   DrivingBehaviorDetector             0x000000010375bca5 kfun:kotlin.Exception.<init>(kotlin.String?)kotlin.Exception + 85
        at 2   DrivingBehaviorDetector             0x000000010375b9a5 kfun:kotlin.RuntimeException.<init>(kotlin.String?)kotlin.RuntimeException + 85
        at 3   DrivingBehaviorDetector             0x0000000103781395 kfun:kotlin.native.IncorrectDereferenceException.<init>(kotlin.String)kotlin.native.IncorrectDereferenceException + 85
        at 4   DrivingBehaviorDetector             0x0000000103782568 ThrowIllegalObjectSharingException + 744
        at 5   DrivingBehaviorDetector             0x00000001037d72bc _ZNK27BackRefFromAssociatedObject19ensureRefAccessibleEv + 76
        at 6   DrivingBehaviorDetector             0x00000001037c97c3 -[KotlinBase toKotlin:] + 35
        at 7   DrivingBehaviorDetector             0x00000001037e3ef1 Kotlin_ObjCExport_refFromObjC + 65
        at 8   DrivingBehaviorDetector             0x00000001037c4e37 objc2kotlin.125 + 167
        at 9   Test                                0x000000010340224d $sIeg_IeyB_TR + 45 (/Users/james/Documents/Projects/go/TestMPPforiOS/<compiler-generated>:<unknown>)
        at 10  libdispatch.dylib                   0x0000000103959dd4 _dispatch_call_block_and_release + 12
        at 11  libdispatch.dylib                   0x000000010395ad48 _dispatch_client_callout + 8
        at 12  libdispatch.dylib                   0x000000010396c460 _dispatch_root_queue_drain + 819
        at 13  libdispatch.dylib                   0x000000010396cb96 _dispatch_worker_thread2 + 132
        at 14  libsystem_pthread.dylib             0x00007fff5245f6b3 _pthread_wqthread + 583
        at 15  libsystem_pthread.dylib             0x00007fff5245f3fd start_wqthread + 13
(lldb) 

我在这些文章中调查了解决方案:

Kotlin/Native 中的不变性:Kotlin/Native 中的不变性 https://kotlinlang.org/docs/reference/native/immutability.html

协程和 K/N 的不变性:K/N 的协程和不变性 https://medium.com/quick-code/kotlin-native-ios-a1a73d7390fe.

我的API(共享库)的入口如下:

class DrivingBehaviorDetector (
    private var gravity:Vector?,
    private var front:Vector?,
    onGravityOrFrontChanged: ((newGravity: Vector?, newFront: Vector?, timestamp: Long) -> Unit)?,
    onDrivingEventDetected: ((event: DrivingEvent) -> Unit)?
) {

    private val lowPassFilter = LowPassFilter()
    private val accProcessor = AccProcessor(gravity, front, onGravityOrFrontChanged, onDrivingEventDetected)

    init {
        gravity = gravity?.toCoreUnit()
        front = front?.toCoreUnit()
    }

    fun addData(data:Acceleration) {
        val rawAcc = data.toCoreUnit()
        val filterAcc = lowPassFilter.lowPass(rawAcc)
        accProcessor.addData(filterAcc)
    }

    fun addData(data:List<Acceleration>) {
        for(acc in data) {
            addData(acc)
        }
    }
}

我们可以注意到 API 非常简单,只需输入大量数据并回调一些计算的结果即可。但在iOS中抛出异常,代码如下:

let drivingBehaviorDetector = DrivingBehaviorDetector(gravity: nil, front: nil, onGravityOrFrontChanged: { (newGravity, newFront, timestamp) in
    print("newGravity = \(newGravity)")
    print("newFront = \(newFront)")
}) { (event) in
    print("event = \(event.description())")
}

let acc1 = Acceleration(vector: Vector(x: 0, y: 0, z: 0))
let acc2 = Acceleration(vector: Vector(x: 0, y: 100, z: 0))

drivingBehaviorDetector.addData(data: acc1)

DispatchQueue.global(qos: .background).async {
    drivingBehaviorDetector.addData(data: acc2)
}

我能想到的唯一一个解决方案是强制在同一线程中使用 API,但这似乎有点奇怪。是否可以通过修改共享库来解决这个问题。因为 mu 的使用很简单,只有一个“DrivingBehaviorDetector”,但它可以在不同的线程中调用“addData”函数。谢谢回答。


对于 Kotlin/Native,必须明确定义正确的并发行为,以避免竞争。在这种特殊情况下,有几种选择:

  • make drivingBehaviorDetector实例冻结(通过调用freeze()例如,在构造函数中),并实现addData()使用并发安全机制,例如冻结样本数据的链表或使用 Swift 集合实例
  • 考虑应用程序中的线程关联性,并决定谁是线程的所有者drivingBehaviorDetector实例,仅在该上下文/线程/队列中实例化和使用此实例,通过调度程序 API 强制执行
  • 有专用的工作程序/协程处理样本并将样本发送给该工作程序,就像在视频样本播放器中所做的那样https://github.com/JetBrains/kotlin-native/blob/8f7ebe7f511d5700cf559c854f9202bf55240e11/samples/videoplayer/src/videoPlayerMain/kotlin/DecoderWorker.kt#L384 https://github.com/JetBrains/kotlin-native/blob/8f7ebe7f511d5700cf559c854f9202bf55240e11/samples/videoplayer/src/videoPlayerMain/kotlin/DecoderWorker.kt#L384
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

未捕获的 Kotlin 异常:kotlin.native.In CorrectDereferenceException:非法尝试访问非共享 的相关文章

  • 检查 switch 语句中的可用性

    if a Enum输入添加新的case在新的操作系统版本中 如何检查可用性switch陈述 像一个Enum in StoreKit below public enum Code Int public typealias ErrorType
  • 二元运算符“&=”不能应用于 Swift 中的两个“Bool”操作数

    我正在尝试进行多次检查 将结果累积在Bool 我的代码是 var validParams login characters count gt 4 validParams password characters count gt 6 vali
  • 从方案加载 url 第一次未处理 - appdelegate 与 viewcontroller

    我的应用程序已成功打开并将参数 从 URL 方案 即 myApp sometextToPrint 设置为AppDelegate类 但每当我想处理它们时 当从该 URL 打开应用程序时 它就会在第一次失败 我在前台检查器中有一个应用程序 它调
  • 如何通过 swift 包管理器在 swift 项目中添加 Alamofire [关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 我正在探索 SPM 现在我需要知道如何在我的项目中通过 SPM 导入 Alamofire 创建一个名为的 swift 文件Package在你
  • Swift 3 Web 视图

    所以我刚刚更新到新的Xcode8 and Swift3但现在我的网络视图不起作用 这是我使用的代码 UIWebView loadRequest webView NSURLRequest URL NSURL string http hardw
  • 如何查看iOS11屏幕录制是否开启?

    为了检测 iOS11 屏幕录制功能的开或关 我使用了 isCaptured 和 UIScreenCapturedDidChange 通知 当我第一次启动应用程序并在 iOS11 内置屏幕录制功能上时 它会通知选择器方法 值为 True 但是
  • 无效的 Swift 支持 - 文件位置不正确

    我一直在尝试将新版本上传到 iTunes Connect 来更新应用程序 我第一次使用 xCode 6 但收到了一封来自 Apple 的电子邮件 内容如下 亲爱的开发者 我们发现您最近交付的 应用程序 存在一个或多个问题 要处理您的交货 必
  • 在 iOS Cocoa 静态库项目中使用 Objective-C 代码,在 iOS 应用程序项目中使用 Swift 代码

    我正在寻找一个简单的过程 用于将共享库项目中的 Objective C 代码与应用程序项目中的 Swift 代码相结合 但到目前为止 此序列尚未成功 启动Xcode 6 1 1 创建工作区测试 创建iOS Cocoa Touch静态库项目T
  • 将 swift 结构体转换为 json 字符串

    我正在尝试将我的 swift 结构转换为 json 格式 类似这样的问题似乎有不少 但到目前为止 没有一个解决方案对我有用 这是我的结构 struct Rec Codable var name String var time Int var
  • 转换任何对象?到字符串

    我有一个返回 AnyObject 的函数 func aFunction param String gt AnyObject 如何将其转换为字符串 和字符串 尝试这个 if let result aFunction test as Strin
  • 如何显示启动图像

    我是 iOS 新手 我的 Xcode 版本是 7 2 1 我尝试使用 Swift 在 iOS9 上运行 我的问题是我对如何创建启动屏幕图像感到非常困惑 我发现有很多方法可以为不同版本的 iOS 创建启动屏幕图像 有人可以向我解释一下如何设置
  • 在 Swift 中使用显式对象类型迭代数组

    我有一个数组 let individualScores 75 43 103 87 12 我这样迭代 for score in individualScores 但是 有没有办法显式声明对象类型呢 我认为以后使用自定义对象或其他原因它会派上用
  • CoreBluetooth 功能无法从 Singleton 运行

    所以我目前在 iPad 和 iPhone 之间建立了蓝牙连接 我已经在中创建了我的测试代码ViewController一切正常 现在我把它移到了 2 个经理类 第一个是CBCentralManager和一个用于CBPeripheralMan
  • 如何立即开始执行 Kotlin 协程

    我想立即启动一个协程 我有一段代码 class SampleActivity AppCompatActivity CoroutineScope private var job Job Job override val coroutineCo
  • 身份验证后如何退出 Google

    所以我的应用程序可以选择使用 Google 登录 单击 Google 提供的按钮后 将打开一个 Web 视图并让用户输入其凭据 允许应用程序访问其信息后 应用程序将用户登录并将 SignInViewController 更改为 TabBar
  • 如何为具有圆角的精灵设置物理体

    我创建了一个SKShapeNode通过以下方式 let sprite SKShapeNode rect CGRect x 20 y 10 width 40 height 20 cornerRadius 10 我也像这样设置了一个物理体 sp
  • 在 Android 中启用展开布局时,如何默认使用折叠布局显示自定义通知

    当用户折叠或展开通知时 我想通过支持小型和大型布局来显示我的自定义通知 如上面的屏幕截图所示 但结果它默认显示扩展通知 我想默认将其显示为折叠通知 并且仅在用户展开时显示展开通知 请检查我的代码如下 private fun initCust
  • 缩进 UILabel 的第二行(swift)

    var testLabel UILabel frame CGRectMake 8 0 tableView frame width 8 100 let testDesc dsfdddfdsfdsfsdfdsfdsfdsfdsfdsfsdfds
  • 找不到 `activityViewModels()` Hilt Android

    我在我的项目中使用 Hilt 和 MVVM 我想要一个viewModel from activityViewModel在 2 个活动中使用相同的内容 但我的 Android Studio 说未解析的参考 我的应用程序 build gradl
  • 如何在 Swift 中的标签上制作阴影效果?

    我不知道如何在标签上编写阴影代码 我有一个会改变的乐谱标签 因此无法仅对带有阴影的文本进行Photoshop处理 我需要对其进行编码 以便它始终自动在文本后面有一个模糊的阴影 有人可以举一些例子或提供帮助吗 人们说这是重复的 重复 是关于

随机推荐