fix(android): bound JNI references and runtime workers#1370
Open
maybeknott wants to merge 2 commits into
Open
Conversation
Android JNI entry points return string payloads for version checks, log drains, update checks, SNI probes, live stats, and pipeline diagnostics. Several of those methods are invoked repeatedly by the Kotlin UI while the proxy is running, so each path should keep JNI local-reference ownership explicit and bounded even when future payload construction adds intermediate Java objects. Add a shared string_to_jstring helper that builds returned Java strings inside an explicit local frame with with_local_frame_returning_local. The frame preserves only the returned jstring for the JVM caller and releases temporary local handles before the native method exits. Allocation or frame setup failures continue to return a null jstring, preserving the existing failure contract. Route every Android string-returning native entry point through the helper without changing payload contents, method names, signatures, threading behavior, or Kotlin call sites. This keeps repeated telemetry and diagnostics polling from relying on the implicit native-method frame and gives the JNI boundary a single audited conversion path.
Android startup built the long-lived proxy Tokio runtime with a fixed four-worker pool on every device. That is unnecessarily large on low-core phones, tablets in power-saving mode, and embedded Android targets, while still being capped enough that larger devices do not need more than a small bounded pool for this local proxy workload. Add a dedicated worker-count helper for the Android proxy runtime. It reads the platform's available parallelism when the runtime starts, falls back to the minimum proxy-safe worker count when the value is unavailable, and clamps the result between two and four workers. The lower bound keeps accept, tunnel, stats, and shutdown work from competing on a single worker; the upper bound preserves the previous maximum and avoids creating a wider scheduler on constrained mobile CPUs. Use the computed value when constructing the runtime and log the selected worker count once during startup. One-shot JNI runtimes used for probes and certificate operations remain current-thread runtimes, and no Kotlin method signatures, config fields, proxy routing behavior, or Android lifecycle contracts change.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Android JNI and runtime setup now keep resource ownership bounded on mobile devices.
This PR has two focused changes in
src/android_jni.rs:jstringfor the JVM caller and releasing temporary handles before native methods exit;The JNI change protects repeated version, log, stats, update, SNI probe, and diagnostics calls from accumulating unmanaged local references as those paths evolve. Allocation or frame setup failures still return a null string, preserving the existing failure contract.
The runtime sizing change keeps at least two workers for accept, tunnel, stats, and shutdown work while avoiding unnecessary scheduler width on low-core phones, tablets in power-saving mode, and embedded Android targets. One-shot JNI runtimes used for probes and certificate operations remain current-thread runtimes.
No Kotlin method signatures, config fields, proxy routing behavior, payload contents, or Android lifecycle contracts change.