From baf651f604f49ec37caaae5bc462e42d641018e4 Mon Sep 17 00:00:00 2001 From: ReigenArataka-jp Date: Mon, 1 Jun 2026 21:37:14 +0300 Subject: [PATCH] Sanitize tooling server JVM environment --- .../services/builder/ToolingServerRunner.kt | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/itsaky/androidide/services/builder/ToolingServerRunner.kt b/app/src/main/java/com/itsaky/androidide/services/builder/ToolingServerRunner.kt index 9755d1fde0..15e6963156 100644 --- a/app/src/main/java/com/itsaky/androidide/services/builder/ToolingServerRunner.kt +++ b/app/src/main/java/com/itsaky/androidide/services/builder/ToolingServerRunner.kt @@ -19,7 +19,6 @@ package com.itsaky.androidide.services.builder import ch.qos.logback.core.CoreConstants import com.itsaky.androidide.logging.JvmStdErrAppender -import com.itsaky.androidide.shell.executeProcessAsync import com.itsaky.androidide.tasks.cancelIfActive import com.itsaky.androidide.tasks.ifCancelledOrInterrupted import com.itsaky.androidide.tooling.api.IToolingApiClient @@ -80,6 +79,20 @@ internal class ToolingServerRunner( * forcibly killing the daemon process tree if it's still alive. */ val TOOLING_DAEMON_KILL_TIMEOUT = 3.seconds + + /** + * Android/ART classpath variables must not be inherited by the standalone + * OpenJDK process used for the tooling API. Some OEM framework images contain + * stale entries here (for example Huawei/Honor UniPerf classes) that can make + * native ART registration abort the JVM before the server starts. + */ + private val ANDROID_RUNTIME_ENV_KEYS = setOf( + "BOOTCLASSPATH", + "DEX2OATBOOTCLASSPATH", + "SYSTEMSERVERCLASSPATH", + "STANDALONE_SYSTEMSERVER_JARS", + "CLASSPATH", + ) } fun setListener(listener: OnServerStartListener?) { @@ -123,15 +136,21 @@ internal class ToolingServerRunner( Environment.TOOLING_API_JAR.absolutePath, ) - process = - executeProcessAsync { - this.command = command + val sanitizedEnv = envs.filterKeys { it !in ANDROID_RUNTIME_ENV_KEYS } + process = + ProcessBuilder(command).run { // input and output is used for communication to the tooling server // error stream is used to read the server logs - this.redirectErrorStream = false - this.workingDirectory = null // HOME - this.environment = envs + redirectErrorStream(false) + directory(Environment.HOME) + + // Do not inherit the app process environment. Inheriting Android runtime + // classpath variables can crash the standalone OpenJDK process on some + // OEM images before our tooling server is initialized. + environment().clear() + environment().putAll(sanitizedEnv) + start() } pid =