KevinnZou / compose-webview-multiplatform

WebView for JetBrains Compose Multiplatform
https://kevinnzou.github.io/compose-webview-multiplatform/
Apache License 2.0
305 stars 39 forks source link

App only works once when initially downloading kcef-bundle #104

Closed KevinLu closed 2 months ago

KevinLu commented 3 months ago

build.gradle.kts:

import org.jetbrains.compose.ExperimentalComposeLibrary
import org.jetbrains.compose.desktop.application.dsl.TargetFormat

plugins {
    alias(libs.plugins.kotlinMultiplatform)
    alias(libs.plugins.kotlinSerialization)
    alias(libs.plugins.jetbrainsCompose)
}

repositories {
    mavenCentral()
    maven("https://jogamp.org/deployment/maven")
}

kotlin {
    jvm("desktop")

    sourceSets {
        val desktopMain by getting

        commonMain.dependencies {
            implementation(compose.runtime)
            implementation(compose.foundation)
            implementation(compose.material)
            implementation(compose.ui)
            @OptIn(ExperimentalComposeLibrary::class)
            implementation(compose.components.resources)
            implementation(libs.ktor.client.core)
            implementation("com.aallam.openai:openai-client:3.6.3")
            implementation("io.github.kevinnzou:compose-webview-multiplatform:1.8.8")
        }
        desktopMain.dependencies {
            implementation(compose.desktop.currentOs)
            implementation(libs.ktor.client.apache5)
            implementation(libs.supabase.postgres)
            implementation(libs.supabase.functions)
            implementation("org.slf4j:slf4j-simple:1.7.36")
        }
    }
}

compose.desktop {
    application {
        mainClass = "MainKt"

        nativeDistributions {
            targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
            packageName = "org.example.project"
            packageVersion = "1.0.0"
            buildTypes.release.proguard {
                isEnabled.set(false)
            }
        }
    }
}

afterEvaluate {
    tasks.withType<JavaExec> {
        jvmArgs("--add-opens", "java.desktop/sun.awt=ALL-UNNAMED")
        jvmArgs("--add-opens", "java.desktop/java.awt.peer=ALL-UNNAMED")

        if (System.getProperty("os.name").contains("Mac")) {
            jvmArgs("--add-opens", "java.desktop/sun.awt=ALL-UNNAMED")
            jvmArgs("--add-opens", "java.desktop/sun.lwawt=ALL-UNNAMED")
            jvmArgs("--add-opens", "java.desktop/sun.lwawt.macosx=ALL-UNNAMED")
        }
    }
}

I'm saving the kcef-bundle like this, as specified in the README in Main.kt:

var restartRequired by remember { mutableStateOf(false) }
                  var downloading by remember { mutableStateOf(0F) }
                  var initialized by remember { mutableStateOf(false) }

                  LaunchedEffect(Unit) {
                      withContext(Dispatchers.IO) {
                          KCEF.init(builder = {
                              installDir(File("kcef-bundle"))
                              progress {
                                  onDownloading {
                                      downloading = max(it, 0F)
                                  }
                                  onInitialized {
                                      initialized = true
                                  }
                              }
                              settings {
                                  cachePath = File("cache").absolutePath
                              }
                          }, onError = {
                              it?.printStackTrace()
                          }, onRestartRequired = {
                              restartRequired = true
                          })
                      }
                  }

                  if (restartRequired) {
                      Text(text = "Restart required.")
                  } else {
                      if (initialized) {
                          displayMap(googleMapsToken)
                      } else {
                          Text(text = "Downloading $downloading%")
                      }
                  }

                  DisposableEffect(Unit) {
                      onDispose {
                          KCEF.disposeBlocking()
                      }
                  }

Reprod steps:

  1. Run project with ./gradlew run
  2. Project runs successfully and kcef-bundle is downloaded into correct folder
  3. Close the app
  4. Run again project with ./gradlew run
  5. App crashes with the following error
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ff9bc1763f6, pid=17108, tid=2724
#
# JRE version: OpenJDK Runtime Environment Zulu17.46+19-CA (17.0.9+8) (build 17.0.9+8-LTS)
# Java VM: OpenJDK 64-Bit Server VM Zulu17.46+19-CA (17.0.9+8-LTS, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, windows-amd64)
# Problematic frame:
# V  [jvm.dll+0x1c63f6]
#
# No core dump will be written. Minidumps are not enabled by default on client versions of Windows
#
# If you would like to submit a bug report, please visit:
#   http://www.azul.com/support/
#

---------------  S U M M A R Y ------------

Command Line: --add-opens=java.desktop/sun.awt=ALL-UNNAMED --add-opens=java.desktop/java.awt.peer=ALL-UNNAMED -Dfile.encoding=UTF-8 -Duser.country=US -Duser.language=en -Duser.variant MainKt

Host: Windows 10 , 64 bit Build 19041
Time: Sat Feb 10 18:35:26 2024

---------------  T H R E A D  ---------------

Current thread (0x000001b819c08650):  JavaThread "AWT-EventQueue-0" [_thread_in_vm, id=2724, stack(0x0000006261200000,0x0000006261300000)]

Stack: [0x0000006261200000,0x0000006261300000],  sp=0x00000062612fdee0,  free space=1015k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [jvm.dll+0x1c63f6]
V  [jvm.dll+0x3e5564]
C  [jcef.dll+0x3c39b]

Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j  org.cef.browser.CefBrowser_N.N_CreateBrowser(Lorg/cef/handler/CefClientHandler;JLjava/lang/String;ZZLjava/awt/Component;Lorg/cef/browser/CefRequestContext;)Z+0
j  org.cef.browser.CefBrowser_N.lambda$createBrowser$1(Lorg/cef/handler/CefClientHandler;JLjava/lang/String;ZZLjava/awt/Component;)V+35
j  org.cef.browser.CefBrowser_N$$Lambda$188+0x000001b81b2b18d0.run()V+28
j  org.cef.browser.CefBrowser_N.executeNative(Ljava/lang/Runnable;Ljava/lang/String;)V+15
j  org.cef.browser.CefBrowser_N.createBrowser(Lorg/cef/handler/CefClientHandler;JLjava/lang/String;ZZLjava/awt/Component;)V+64
j  org.cef.browser.CefBrowserWr.createBrowserIfRequired(Z)Z+104
j  org.cef.browser.CefBrowserWr$1$1.run()V+151
j  java.awt.event.InvocationEvent.dispatch()V+47 java.desktop@17.0.9
j  java.awt.EventQueue.dispatchEventImpl(Ljava/awt/AWTEvent;Ljava/lang/Object;)V+21 java.desktop@17.0.9
j  java.awt.EventQueue$4.run()Ljava/lang/Void;+32 java.desktop@17.0.9
j  java.awt.EventQueue$4.run()Ljava/lang/Object;+1 java.desktop@17.0.9
J 993 c1 java.security.AccessController.executePrivileged(Ljava/security/PrivilegedAction;Ljava/security/AccessControlContext;Ljava/lang/Class;)Ljava/lang/Object; java.base@17.0.9 (65 bytes) @ 0x000001b8001aa63c [0x000001b8001aa4e0+0x000000000000015c]
j  java.security.AccessController.doPrivileged(Ljava/security/PrivilegedAction;Ljava/security/AccessControlContext;)Ljava/lang/Object;+13 java.base@17.0.9
j  java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Ljava/security/PrivilegedAction;Ljava/security/AccessControlContext;Ljava/security/AccessControlContext;)Ljava/lang/Object;+18 java.base@17.0.9
j  java.awt.EventQueue.dispatchEvent(Ljava/awt/AWTEvent;)V+46 java.desktop@17.0.9
j  java.awt.EventDispatchThread.pumpOneEventForFilters(I)V+78 java.desktop@17.0.9
j  java.awt.EventDispatchThread.pumpEventsForFilter(ILjava/awt/Conditional;Ljava/awt/EventFilter;)V+35 java.desktop@17.0.9
j  java.awt.EventDispatchThread.pumpEventsForHierarchy(ILjava/awt/Conditional;Ljava/awt/Component;)V+11 java.desktop@17.0.9
j  java.awt.EventDispatchThread.pumpEvents(ILjava/awt/Conditional;)V+4 java.desktop@17.0.9
j  java.awt.EventDispatchThread.pumpEvents(Ljava/awt/Conditional;)V+3 java.desktop@17.0.9
j  java.awt.EventDispatchThread.run()V+9 java.desktop@17.0.9
v  ~StubRoutines::call_stub

siginfo: EXCEPTION_ACCESS_VIOLATION (0xc0000005), reading address 0x0000000000000000
KevinnZou commented 3 months ago

@KevinLu Thanks for your feedback! It seems to do with the read access. Could you try to delete the kcef-bundle and try again?

KevinLu commented 2 months ago

@KevinLu Thanks for your feedback! It seems to do with the read access. Could you try to delete the kcef-bundle and try again?

I've tried deleting that folder and re-running my app. The same thing happens, when the folder is first created and the bundle is downloaded, it works fine. But when I relaunch my app with the existing bundle, it just crashes.

KevinnZou commented 2 months ago

@DatL4g Could you have a look at this issue?

DatL4g commented 2 months ago

This may be caused by multiple factors and a JVM crash is hard to debug.

Since it's working after the download, make sure to add the jvmArgs correctly, follow the guide. Your current implementation may come too late.

Then it's either insufficient access rights for the folder (make sure the user has read, write and execute permissions) or something like an antivirus is locking these permissions away: https://youtrack.jetbrains.com/issue/IDEA-256519/EXCEPTIONACCESSVIOLATION-random-crash-on-Windows