在 Compose Multiplatform 中使用 Koin 在 ViewModel 中加载本机库时 JVM 崩溃

问题描述 投票:0回答:1

我正在开发一个在 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

任何有关如何解决此问题的指导将不胜感激!

kotlin jvm kotlin-multiplatform koin compose-multiplatform
1个回答
0
投票

所以,我还没有找到它的确切原因,但只有在使用 Koin 创建对象时加载本机库时才会发生。

最简单的解决方案是在其外部加载库。

© www.soinside.com 2019 - 2024. All rights reserved.