From b22e2d8edfdce3bfe21dbf7d5cc7571129494b84 Mon Sep 17 00:00:00 2001 From: Ced Naru Date: Sat, 27 Apr 2024 07:03:53 +0200 Subject: [PATCH] Disable JVM reloading --- .../main/kotlin/godot/runtime/Bootstrap.kt | 93 ++----------------- src/gd_kotlin.cpp | 31 ++++--- 2 files changed, 28 insertions(+), 96 deletions(-) diff --git a/kt/godot-library/src/main/kotlin/godot/runtime/Bootstrap.kt b/kt/godot-library/src/main/kotlin/godot/runtime/Bootstrap.kt index b1a562f78b..e9340887c9 100644 --- a/kt/godot-library/src/main/kotlin/godot/runtime/Bootstrap.kt +++ b/kt/godot-library/src/main/kotlin/godot/runtime/Bootstrap.kt @@ -7,27 +7,15 @@ import godot.core.variantMapper import godot.registration.ClassRegistry import godot.registration.Entry import godot.util.err -import godot.util.info -import godot.util.warning import java.io.File import java.net.URL import java.net.URLClassLoader -import java.nio.file.FileSystems -import java.nio.file.StandardWatchEventKinds -import java.nio.file.WatchService import java.util.* -import java.util.concurrent.Executors -import java.util.concurrent.ScheduledExecutorService -import java.util.concurrent.TimeUnit internal class Bootstrap { - private val classRegistries: MutableList = mutableListOf() private lateinit var classloader: ClassLoader private lateinit var serviceLoader: ServiceLoader - private var executor: ScheduledExecutorService? = null - private var watchService: WatchService? = null - private var engineTypesRegistered: Boolean = false /** projectRootDir is empty if not in editor (only used for reloading) * userCodePath is empty if usercode loaded as part of the VM @@ -38,67 +26,18 @@ internal class Bootstrap { doInitGraal() } else { val userCodeFile = File(userCodePath) - - if (userCodeFile.exists()) { - doInit(userCodeFile.toURI().toURL(), loader) - } else { - if (projectRootDir.isNotEmpty()) { - ::warning - } else { - ::err - }.invoke("No main.jar detected at $userCodeFile. No classes will be loaded. Build the gradle project to load classes") - } - - if (projectRootDir.isNotEmpty()) { - watchService = FileSystems.getDefault().newWatchService() - val watchKey = getBuildLockDir(projectRootDir).toPath().register( - watchService, - StandardWatchEventKinds.ENTRY_CREATE, - StandardWatchEventKinds.ENTRY_DELETE, - StandardWatchEventKinds.ENTRY_MODIFY, - ) - - executor = Executors.newSingleThreadScheduledExecutor { runnable -> - val thread = Thread(runnable) - thread.isDaemon = true - thread - } - - executor!!.scheduleAtFixedRate({ - val events = watchKey.pollEvents() - if (events.isNotEmpty()) { - if (File(getBuildLockDir(projectRootDir), "buildLock.lock").exists()) { - info("Build lock present. Not reloading...") - return@scheduleAtFixedRate - } - info("Changes detected, reloading classes ...") - - if (::serviceLoader.isInitialized) { - clearClassesCache() - serviceLoader.reload() - } - - if (userCodeFile.exists()) { - doInit(userCodeFile.toURI().toURL(), null) //no classloader so new main jar gets loaded - } else { - warning("No main.jar detected. No classes will be loaded. Build the project to load classes") - } - } - }, 3, 3, TimeUnit.SECONDS) - } + doInit(userCodeFile.toURI().toURL(), loader) } } fun finish() { - executor?.shutdown() - watchService?.close() + Thread.currentThread().contextClassLoader = null clearClassesCache() serviceLoader.reload() } private fun doInit(mainJar: URL, classLoader: ClassLoader?) { classloader = classLoader ?: URLClassLoader(arrayOf(mainJar), this::class.java.classLoader) - Thread.currentThread().contextClassLoader = classloader serviceLoader = ServiceLoader.load(Entry::class.java, classloader) initializeUsingEntry() } @@ -123,6 +62,7 @@ internal class Bootstrap { // the entry with the most class registrars is always the "main" entry. All other entries are from dependencies // reason: the "main" compilation generates the registration files from all class registrars (its own AND all from dependencies). Hence, it will always be the one with the highest registrar count val mainEntry = entries.maxBy { entry -> entry.classRegistrarCount } + val classRegistries = mutableListOf() entries.forEach { entry -> val isMainEntry = entry == mainEntry @@ -131,23 +71,21 @@ internal class Bootstrap { projectName = entry.projectName, isDependency = !isMainEntry, ) - classRegistries.add(registry) + classRegistries.add(registry) val context = Entry.Context(registry) with(entry) { - if (!engineTypesRegistered && isMainEntry) { + if (isMainEntry) { context.initEngineTypes() - for (clazz in context.getRegisteredClasses()) { - variantMapper[clazz] = VariantType.OBJECT - } registerManagedEngineTypes( TypeManager.engineTypeNames.toTypedArray(), TypeManager.engineSingletonsNames.toTypedArray() ) - engineTypesRegistered = true } - + for (clazz in context.getRegisteredClasses()) { + variantMapper[clazz] = VariantType.OBJECT + } context.init() } } @@ -162,22 +100,7 @@ internal class Bootstrap { // END: order matters! } - private fun getBuildLockDir(projectDir: String): File { - val name = "${File(projectDir).name}_buildLockDir" //keep the same in the gradle plugin! - val tmpDir = System.getProperty("java.io.tmpdir") - val lockDir = File(tmpDir, name) - - return if (lockDir.exists() && lockDir.isDirectory) { - lockDir - } else { - lockDir.delete() - lockDir.mkdirs() - lockDir - } - } - private fun clearClassesCache() { - classRegistries.clear() TypeManager.clearUserTypes() } diff --git a/src/gd_kotlin.cpp b/src/gd_kotlin.cpp index ca34684c4a..f74292a69e 100644 --- a/src/gd_kotlin.cpp +++ b/src/gd_kotlin.cpp @@ -269,15 +269,25 @@ bool GDKotlin::load_user_code() { #else String user_code_path {copy_new_file_to_user_dir(USER_CODE_FILE)}; #endif - if (!FileAccess::exists(user_code_path)) { return false; } + if (!FileAccess::exists(user_code_path)) { + String message {"No main.jar detected at $userCodeFile. No classes will be loaded. Build the gradle " + "project to load classes"}; +#ifdef TOOLS_ENABLED + LOG_WARNING(vformat(message, user_code_path)); +#elif defined DEBUG_ENABLED + LOG_ERROR(vformat(message, user_code_path)); +#endif + return false; + } LOG_VERBOSE(vformat("Loading usercode file at: %s", user_code_path)); - // TODO: Rework this part when cpp reloading done, can't check what's happening in the Kotlin code from here. + ClassLoader* user_class_loader = ClassLoader::create_instance( env, ProjectSettings::get_singleton()->globalize_path(user_code_path), bootstrap_class_loader->get_wrapped() ); + bootstrap->init( env, project_path, @@ -317,12 +327,11 @@ void GDKotlin::unload_boostrap() { bootstrap_class_loader = nullptr; } - #define SET_LOADING_STATE(cond, new_state, target_state) \ - if (state < State::new_state) { \ - if (!cond) { return; } \ - state = State::new_state; \ - if (new_state == target_state) { return; } \ + if (state < State::new_state) { \ + if (!cond) { return; } \ + state = State::new_state; \ + if (new_state == target_state) { return; } \ } void GDKotlin::initialize_up_to(State target_state) { @@ -341,10 +350,10 @@ void GDKotlin::initialize_up_to(State target_state) { } #define UNSET_LOADING_STATE(function, new_state, target_state) \ - if (state > State::new_state) { \ - function; \ - state = State::new_state; \ - if (new_state == target_state) { return; } \ + if (state > State::new_state) { \ + function; \ + state = State::new_state; \ + if (new_state == target_state) { return; } \ } void GDKotlin::finalize_down_to(State target_state) {