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
相关产品推荐
相关产品推荐

