我正在开发一个在 Linux (x86_64) 上运行的 Compose 多平台应用程序。我有一个类
DesktopNativeClient
加载本机库,如下所示:
class DesktopNativeClient {
private companion object {
private val logger = Logger.withTag("NativeClient")
private const val NATIVE_LIBRARY_PATH = "/path/to/lib.so"
init {
logger.d { "Loading native library" }
System.load(NATIVE_LIBRARY_PATH)
logger.d { "Loaded native library" }
}
}
}
当我在
main
函数中加载本机库时,一切正常:
fun main() = application {
DesktopNativeClient()
Window(
onCloseRequest = ::exitApplication,
title = "Title",
state = rememberWindowState(
width = ...,
height = ...
),
) {
MainApp()
}
}
但是,当我尝试在通过 Koin 提供的
ViewModel
中加载本机库时,我总是在加载本机库时遇到 JVM 崩溃:
class AppViewModel {
private val nativeClient = DesktopNativeClient()
...
}
ViewModel
的创建方式如下:
actual val platformAppModule = module {
factory<BaseAppViewModel> {
AppViewModel(
defaultDispatcher = get(named(DispatchersNames.DEFAULT)),
ioDispatcher = get(named(DispatchersNames.IO)),
mainDispatcher = get(named(DispatchersNames.MAIN)),
)
}
}
并注入:
// in commonMain:
@Composable
expect inline fun <reified T : BaseAppViewModel> AppScreen(viewModel: T = koinNavViewModel())
// in desktopMain:
@Composable
actual inline fun <T : BaseAppViewModel> AppScreen(viewModel: T) {
...
崩溃日志:
Current thread (0x000074a7c88a1530): JavaThread "AWT-EventQueue-0" [_thread_in_native, id=49176, stack(0x000074a760d4e000,0x000074a760e4e000)]
Stack: [0x000074a760d4e000,0x000074a760e4e000], sp=0x000074a760e48420, free space=1001k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C [libstdc++.so.6+0xeeb05] std::ctype<wchar_t>::do_scan_is(unsigned short, wchar_t const*, wchar_t const*) const+0x35
C [libstdc++.so.6+0xe631e] void std::__facet_shims::__numpunct_fill_cache<char>(std::integral_constant<bool, false>, std::locale::facet const*, std::__numpunct_cache<char>*)+0x6e
C [libstdc++.so.6+0xeb947] std::locale::facet::_M_sso_shim(std::locale::id const*) const+0x237
C [libstdc++.so.6+0xc46e9] std::locale::_Impl::_M_install_facet(std::locale::id const*, std::locale::facet const*)+0x229
C [libstdc++.so.6+0xdd8c3] std::locale::_Impl::_Impl(unsigned long)+0x653
C [libstdc++.so.6+0xde125] std::locale::_S_initialize_once()+0x35
C [libc.so.6+0x998fb]
C [libc.so.6+0x99979] pthread_once+0x19
C [libstdc++.so.6+0xde188] std::locale::_S_initialize()+0x38
C [libstdc++.so.6+0xde1e1] std::locale::locale()+0x21
C [libstdc++.so.6+0xc259b] std::ios_base::Init::Init()+0xeb
C [libstdc++.so.6+0xaa1cd] _GLOBAL__sub_I.00090_globals_io.cc+0x1d
C [libc.so.6+0x8ff14]
C [ld-linux-x86-64.so.2+0x1523] _dl_catch_exception+0xa3
C [ld-linux-x86-64.so.2+0x1679]
C [libc.so.6+0x8f9f3]
C [libc.so.6+0x8ffcf] dlopen+0x6f
V [libjvm.so+0x8e2030] JVM_LoadLibrary+0xd0
C [libjava.so+0xf1cf] Java_jdk_internal_loader_NativeLibraries_load+0x1df
j jdk.internal.loader.NativeLibraries.load(Ljdk/internal/loader/NativeLibraries$NativeLibraryImpl;Ljava/lang/String;ZZZ)Z+0 [email protected]
j jdk.internal.loader.NativeLibraries$NativeLibraryImpl.open()Z+61 [email protected]
j jdk.internal.loader.NativeLibraries.loadLibrary(Ljava/lang/Class;Ljava/lang/String;Z)Ljdk/internal/loader/NativeLibrary;+256 [email protected]
j jdk.internal.loader.NativeLibraries.loadLibrary(Ljava/lang/Class;Ljava/io/File;)Ljdk/internal/loader/NativeLibrary;+51 [email protected]
j java.lang.ClassLoader.loadLibrary(Ljava/lang/Class;Ljava/io/File;)Ljdk/internal/loader/NativeLibrary;+31 [email protected]
j java.lang.Runtime.load0(Ljava/lang/Class;Ljava/lang/String;)V+61 [email protected]
j java.lang.System.load(Ljava/lang/String;)V+7 [email protected]
j my.packageclient.client.DesktopNativeClient.<clinit>()V+109
v ~StubRoutines::call_stub
j my.packageclient.presentation.apps.detail.AppViewModel.<init>(Lkotlinx/coroutines/CoroutineDispatcher;Lkotlinx/coroutines/CoroutineDispatcher;Lkotlinx/coroutines/CoroutineDispatcher;)V+52
j my.packageclient.di.module.PlatformAppModule_desktopKt.platformAppModule$lambda$1$lambda$0(Lorg/koin/core/scope/Scope;Lorg/koin/core/parameter/ParametersHolder;)Lmy/package/client/presentation/apps/detail/BaseAppViewModel;+100
j my.packageclient.di.module.PlatformAppModule_desktopKt$$Lambda$215+0x000074a70c1e0488.invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+8
j org.koin.core.instance.InstanceFactory.create(Lorg/koin/core/instance/ResolutionContext;)Ljava/lang/Object;+66
j org.koin.core.instance.FactoryInstanceFactory.get(Lorg/koin/core/instance/ResolutionContext;)Ljava/lang/Object;+8
j org.koin.core.registry.InstanceRegistry.resolveInstance$koin_core(Lorg/koin/core/qualifier/Qualifier;Lkotlin/reflect/KClass;Lorg/koin/core/qualifier/Qualifier;Lorg/koin/core/instance/ResolutionContext;)Ljava/lang/Object;+35
j org.koin.core.scope.Scope.resolveFromRegistry(Lorg/koin/core/instance/ResolutionContext;)Ljava/lang/Object;+20
j org.koin.core.scope.Scope.resolveFromContext(Lorg/koin/core/instance/ResolutionContext;)Ljava/lang/Object;+73
j org.koin.core.scope.Scope.stackParametersCall(Lorg/koin/core/parameter/ParametersHolder;Lorg/koin/core/instance/ResolutionContext;)Ljava/lang/Object;+107
j org.koin.core.scope.Scope.resolveInstance(Lorg/koin/core/qualifier/Qualifier;Lkotlin/reflect/KClass;Lorg/koin/core/parameter/ParametersHolder;)Ljava/lang/Object;+77
j org.koin.core.scope.Scope.resolveWithOptionalLogging(Lkotlin/reflect/KClass;Lorg/koin/core/qualifier/Qualifier;Lorg/koin/core/parameter/ParametersHolder;)Ljava/lang/Object;+45
j org.koin.core.scope.Scope.get(Lkotlin/reflect/KClass;Lorg/koin/core/qualifier/Qualifier;Lkotlin/jvm/functions/Function0;)Ljava/lang/Object;+27
j org.koin.viewmodel.factory.KoinViewModelFactory.create(Lkotlin/reflect/KClass;Landroidx/lifecycle/viewmodel/CreationExtras;)Landroidx/lifecycle/ViewModel;+43
j androidx.lifecycle.viewmodel.ViewModelProviderImpl_desktopKt.createViewModel(Landroidx/lifecycle/ViewModelProvider$Factory;Lkotlin/reflect/KClass;Landroidx/lifecycle/viewmodel/CreationExtras;)Landroidx/lifecycle/ViewModel;+21
j androidx.lifecycle.viewmodel.ViewModelProviderImpl.getViewModel$lifecycle_viewmodel(Lkotlin/reflect/KClass;Ljava/lang/String;)Landroidx/lifecycle/ViewModel;+103
j androidx.lifecycle.viewmodel.ViewModelProviderImpl.getViewModel$lifecycle_viewmodel$default(Landroidx/lifecycle/viewmodel/ViewModelProviderImpl;Lkotlin/reflect/KClass;Ljava/lang/String;ILjava/lang/Object;)Landroidx/lifecycle/ViewModel;+17
j androidx.lifecycle.ViewModelProvider.get(Lkotlin/reflect/KClass;)Landroidx/lifecycle/ViewModel;+14
j org.koin.viewmodel.GetViewModelKt.resolveViewModel(Lkotlin/reflect/KClass;Landroidx/lifecycle/ViewModelStore;Ljava/lang/String;Landroidx/lifecycle/viewmodel/CreationExtras;Lorg/koin/core/qualifier/Qualifier;Lorg/koin/core/scope/Scope;Lkotlin/jvm/functions/Function0;)Landroidx/lifecycle/ViewModel;+108
j my.packageclient.presentation.apps.list.RemoteAppsScreenKt.RemoteAppView(Lmy/package/client/presentation/apps/list/RemoteAppsViewModel;Lmy/package/client/presentation/apps/data/AppTab;Landroidx/compose/runtime/Composer;I)V+667
j my.packageclient.presentation.apps.list.RemoteAppsScreenKt$RemoteAppsScreen$4.invoke(Landroidx/compose/foundation/layout/PaddingValues;Landroidx/compose/runtime/Composer;I)V+569
j my.packageclient.presentation.apps.list.RemoteAppsScreenKt$RemoteAppsScreen$4.invoke(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+16
j androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(Ljava/lang/Object;Landroidx/compose/runtime/Composer;I)Ljava/lang/Object;+75
j androidx.compose.runtime.internal.ComposableLambdaImpl$invoke$2.invoke(Landroidx/compose/runtime/Composer;I)V+24
j androidx.compose.runtime.internal.ComposableLambdaImpl$invoke$2.invoke(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;+12
j androidx.compose.runtime.RecomposeScopeImpl.compose(Landroidx/compose/runtime/Composer;)V+86
j androidx.compose.runtime.ComposerImpl.recomposeToGroupEnd()V+209
j androidx.compose.runtime.ComposerImpl.skipCurrentGroup()V+360
j androidx.compose.runtime.ComposerImpl.doCompose(Landroidx/compose/runtime/collection/ScopeMap;Lkotlin/jvm/functions/Function2;)V+585
j androidx.compose.runtime.ComposerImpl.recompose$runtime(Landroidx/compose/runtime/collection/ScopeMap;)Z+72
j androidx.compose.runtime.CompositionImpl.recompose()Z+104
j androidx.compose.runtime.Recomposer.performRecompose(Landroidx/compose/runtime/ControlledComposition;Landroidx/collection/MutableScatterSet;)Landroidx/compose/runtime/ControlledComposition;+141
j androidx.compose.runtime.Recomposer.access$performRecompose(Landroidx/compose/runtime/Recomposer;Landroidx/compose/runtime/ControlledComposition;Landroidx/collection/MutableScatterSet;)Landroidx/compose/runtime/ControlledComposition;+3
j androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$1.invoke(J)V+397
j androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$1.invoke(Ljava/lang/Object;)Ljava/lang/Object;+8
j androidx.compose.runtime.BroadcastFrameClock$FrameAwaiter.resume(J)V+31
j androidx.compose.runtime.BroadcastFrameClock.sendFrame(J)V+78
j androidx.compose.ui.scene.BaseComposeScene.render(Landroidx/compose/ui/graphics/Canvas;J)V+127
j androidx.compose.ui.scene.ComposeSceneMediator$onRender$1$1.invoke()V+141
j androidx.compose.ui.scene.ComposeSceneMediator$onRender$1$1.invoke()Ljava/lang/Object;+1
j androidx.compose.ui.viewinterop.SwingInteropContainer.postponingExecutingScheduledUpdates(Lkotlin/jvm/functions/Function0;)V+83
j androidx.compose.ui.scene.ComposeSceneMediator.onRender(Lorg/jetbrains/skia/Canvas;IIJ)V+35
j org.jetbrains.skiko.SkiaLayer.update$skiko(J)V+223
j org.jetbrains.skiko.redrawer.AWTRedrawer.update(J)V+57
j org.jetbrains.skiko.redrawer.LinuxOpenGLRedrawer$Companion$frameDispatcher$1.invokeSuspend(Ljava/lang/Object;)Ljava/lang/Object;+263
J 2246 c1 kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(Ljava/lang/Object;)V (128 bytes) @ 0x000074a7b161637c [0x000074a7b1615f40+0x000000000000043c]
J 2425 c1 kotlinx.coroutines.DispatchedTask.run()V (400 bytes) @ 0x000074a7b167e8ec [0x000074a7b167d2c0+0x000000000000162c]
J 3697 c1 java.awt.event.InvocationEvent.dispatch()V [email protected] (69 bytes) @ 0x000074a7b1936e9c [0x000074a7b1936c80+0x000000000000021c]
J 3261 c1 java.awt.EventQueue.dispatchEventImpl(Ljava/awt/AWTEvent;Ljava/lang/Object;)V [email protected] (136 bytes) @ 0x000074a7b184afec [0x000074a7b1849500+0x0000000000001aec]
J 3260 c1 java.awt.EventQueue$4.run()Ljava/lang/Void; [email protected] (60 bytes) @ 0x000074a7b184013c [0x000074a7b1840000+0x000000000000013c]
J 3255 c1 java.awt.EventQueue.dispatchEvent(Ljava/awt/AWTEvent;)V [email protected] (80 bytes) @ 0x000074a7b184350c [0x000074a7b1842f60+0x00000000000005ac]
J 3264 c1 java.awt.EventDispatchThread.pumpOneEventForFilters(I)V [email protected] (113 bytes) @ 0x000074a7b1846624 [0x000074a7b1845fa0+0x0000000000000684]
j java.awt.EventDispatchThread.pumpEventsForFilter(ILjava/awt/Conditional;Ljava/awt/EventFilter;)V+35 [email protected]
j java.awt.EventDispatchThread.pumpEventsForHierarchy(ILjava/awt/Conditional;Ljava/awt/Component;)V+11 [email protected]
j java.awt.EventDispatchThread.pumpEvents(ILjava/awt/Conditional;)V+4 [email protected]
j java.awt.EventDispatchThread.pumpEvents(Ljava/awt/Conditional;)V+3 [email protected]
j java.awt.EventDispatchThread.run()V+9 [email protected]
v ~StubRoutines::call_stub
在
ViewModel
中加载本机库时,什么可能导致 JVM 崩溃?
在
Composable
上下文中加载原生库或使用 Koin 时有什么具体注意事项吗?
仅当本地库加载到
ViewModel
(通过Koin注入)时才会发生崩溃。
在
main
函数中加载库时,应用程序运行良好。
我正在使用zulu-17.52
任何有关如何解决此问题的指导将不胜感激!
所以,我还没有找到它的确切原因,但只有在使用 Koin 创建对象时加载本机库时才会发生。
最简单的解决方案是在其外部加载库。