You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

KMM项目遇IncorrectDereferenceException错误,freeze方法无法使用求助

KMM线程安全错误:IncorrectDereferenceException 解决指南

错误信息

Uncaught Kotlin exception: kotlin.native.IncorrectDereferenceException: illegal attempt to access non-shared dev.mrbe.haarShared.HaarSDK@abc468 from other thread
    at 0   kotlinmultiplatformsharedmodule     0x00000001020909a1 kfun:kotlin.Throwable#<init>(kotlin.String?){} + 97 (/opt/buildAgent/work/c5a36d4d82b914cf/kotlin/kotlin-native/runtime/src/main/kotlin/kotlin/Throwable.kt:24:56)
    at 1   kotlinmultiplatformsharedmodule     0x0000000102089dad kfun:kotlin.Exception#<init>(kotlin.String?){} + 93 (/opt/buildAgent/work/c5a36d4d82b914cf/kotlin/kotlin-native/runtime/src/main/kotlin/kotlin/Exceptions.kt:23:58)
    at 2   kotlinmultiplatformsharedmodule     0x0000000102089fcd kfun:kotlin.RuntimeException#<init>(kotlin.String?){} + 93 (/opt/buildAgent/work/c5a36d4d82b914cf/kotlin/kotlin-native/runtime/src/main/kotlin/kotlin/Exceptions.kt:34:58)
    at 3   kotlinmultiplatformsharedmodule     0x00000001020c140d kfun:kotlin.native.IncorrectDereferenceException#<init>(kotlin.String){} + 93 (/opt/buildAgent/work/c5a36d4d82b914cf/kotlin/kotlin-native/runtime/src/main/kotlin/kotlin/native/Runtime.kt:31:50)
    at 4   kotlinmultiplatformsharedmodule     0x00000001020c508f ThrowIllegalObjectSharingException + 623 (/opt/buildAgent/work/c5a36d4d82b914cf/kotlin/kotlin-native/runtime/src/main/kotlin/kotlin/native/concurrent/Internal.kt:115:11)
    at 5   kotlinmultiplatformsharedmodule     0x00000001022a1b52 _ZN12_GLOBAL__N_128throwIllegalSharingExceptionEP9ObjHeader + 34
    at 6   kotlinmultiplatformsharedmodule     0x00000001022a389d _ZN12_GLOBAL__N_136terminateWithIllegalSharingExceptionEP9ObjHeader + 13
    at 7   kotlinmultiplatformsharedmodule     0x00000001022a39b5 _ZNK27BackRefFromAssociatedObject3refIL11ErrorPolicy3EEEP9ObjHeaderv + 133
    at 8   kotlinmultiplatformsharedmodule     0x0000000102070e25 -[KotlinBase toKotlin:] + 21
    at 9   kotlinmultiplatformsharedmodule     0x0000000102295058 Kotlin_ObjCExport_refFromObjC + 88
    at 10  kotlinmultiplatformsharedmodule     0x0000000102040676 objc2kotlin.505 + 230
    at 11  haar                                0x00000001006b3181 $s4haar11MyViewModelC10addBooking7bookingySo031KotlinmultiplatformsharedmoduleF0C_tYaFTY0_ + 273 (/Users/essienedim/Desktop/HAAR /haar/haar/ContentView.swift:422:33)
    at 12  libswift_Concurrency.dylib          0x00007ff833c40426 _ZN5swift34runJobInEstablishedExecutorContextEPNS_3JobE + 310
    at 13  libswift_Concurrency.dylib          0x00007ff833c411bd _ZL17swift_job_runImplPN5swift3JobENS_11ExecutorRefE + 77
    at 14  libdispatch.dylib                   0x00000001014dfe77 _dispatch_continuation_pop + 87
    at 15  libdispatch.dylib                   0x00000001014def27 _dispatch_async_redirect_invoke + 997
    at 16  libdispatch.dylib                   0x00000001014f1e77 _dispatch_root_queue_drain + 414
    at 17  libdispatch.dylib                   0x00000001014f2b17 _dispatch_worker_thread2 + 278
    at 18  libsystem_pthread.dylib             0x00007ff833e39f8a _pthread_wqthread + 256
    at 19  libsystem_pthread.dylib             0x00007ff833e38f57 start_wqthread + 15
CoreSimulator 857.7 - Device: iPhone 14 Pro (C24AA3AD-B79D-437E-BCB7-A15C83C0F412) - Runtime: iOS 16.0 (20A360) - DeviceType: iPhone 14 Pro
(lldb) 

问题背景

刚接触KMM,项目持续抛出上述错误。尝试用freeze()方法解决,但提示Unresolved reference: freeze,不清楚操作有误还是不知道该冻结哪个对象。

相关代码

触发异常的Swift函数

func addBooking(booking: Booking) async {
    await sdk.postBooking(booking: booking)
}

ViewModel初始化(Swift)

class MyViewModel: ObservableObject {
    let sdk: HaarSDK

    // ...

    init(sdk: HaarSDK) {
        self.sdk = sdk
        // ...
    }
}

主视图代码(Swift)

struct MainView: View {
    
    @StateObject private var viewModel: MyViewModel
    
    init() {
        let sdk = HaarSDK(databaseDriverFactory: DatabaseDriverFactory())
        let viewModel = MyViewModel(sdk: sdk)
        _viewModel = StateObject(wrappedValue: viewModel)
    }

    // ...
}

Kotlin端SDK类

class HaarSDK(databaseDriverFactory: DatabaseDriverFactory) {
    private val database = Database(databaseDriverFactory)
    private val api = HaarApi()

    // ...

    @Throws(Exception::class)
    suspend fun postBooking(booking: Booking) {
        api.sendBooking(booking)
    }
    // ...
}

Kotlin端Database类

internal class Database(databaseDriverFactory: DatabaseDriverFactory) {
    private val database by lazy {
        AppDatabase(databaseDriverFactory.createDriver())
    }
    private val dbQuery = database.appDatabaseQueries
    // ...
}

Kotlin端API类

class HaarApi {
    private val httpClient = HttpClient {
        install(JsonFeature) {
            val json = Json { ignoreUnknownKeys = true }
            serializer = KotlinxSerializer(json)
        }
        // ...
    }

    suspend fun sendBooking(booking: Booking) {
        val response: HttpResponse = httpClient.post(BOOKING_ENDPOINT) {
            contentType(ContentType.Application.Json)
            body = booking
        }
        // ...
    }
}

解决方案

1. 解决freeze()未找到的问题

在Kotlin代码中导入对应包,才能使用该方法:

import kotlin.native.concurrent.freeze

2. 确定需要冻结的对象

错误信息明确指出是HaarSDK对象被跨线程访问导致的问题——SDK实例在主线程创建,却在Swift的async后台线程中被调用,而Kotlin Native默认禁止非共享对象跨线程访问。

3. 正确冻结对象的两种方式

方式一:在Kotlin端初始化时自动冻结

修改HaarSDK的构造函数,在初始化完成后冻结自身:

class HaarSDK(databaseDriverFactory: DatabaseDriverFactory) {
    private val database = Database(databaseDriverFactory)
    private val api = HaarApi()

    init {
        freeze()
    }

    // ... 原有方法
}

注意:确保database和api对象本身也是线程安全的,或者也被冻结。如果Database或HaarApi内部有可变状态,需要额外处理线程安全。

方式二:在Swift端创建实例时冻结

在Swift中创建HaarSDK实例后,调用其freeze()方法(KMM生成的类默认继承KotlinBase,支持该方法):

init() {
    let sdk = HaarSDK(databaseDriverFactory: DatabaseDriverFactory())
    sdk.freeze() // 新增冻结调用
    let viewModel = MyViewModel(sdk: sdk)
    _viewModel = StateObject(wrappedValue: viewModel)
}

4. 更优雅的线程安全方案(推荐)

如果不想用freeze()(冻结后对象状态不可变),可以通过协程调度确保suspend函数在合适的线程执行:
修改Kotlin端的postBooking方法,指定调度器:

import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

@Throws(Exception::class)
suspend fun postBooking(booking: Booking) {
    withContext(Dispatchers.Default) {
        api.sendBooking(booking)
    }
}

同时确保HttpClient和数据库操作本身是线程安全的(HttpClient默认是线程安全的,数据库驱动需确认支持多线程访问)。

内容的提问来源于stack exchange,提问作者MrBE

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 22:30:52