Skip to content

[NativeAOT] set environment variables before the app .so is loaded - #10709

Merged
grendello merged 6 commits into
mainfrom
dev/grendel/naot-env
Jan 26, 2026
Merged

[NativeAOT] set environment variables before the app .so is loaded#10709
grendello merged 6 commits into
mainfrom
dev/grendel/naot-env

Conversation

@grendello

@grendellogrendello commented Jan 22, 2026

Copy link
Copy Markdown
Contributor

Fixes: #10705

When a NativeAOT application starts up, certain portions of the managed startup
sequence are executed on the shared library load but before the JNI_OnLoad
function is invoked by Android.

Both MonoVM and CoreCLR hosts set environment variables which may affect the
way the application behaves before they initialize the managed runtime. Those
variables are set from within native code, using data generated at application
build time.

Until now, the NativeAOT host followed suit, but it appears that we need to
set certain variables (e.g. those related to running the startup hooks) before
the shared library is loaded.

The only location where we can do it is the NativeAndroidRuntimeProvider Java
class which is responsible for, eventually, loading the application shared
library.

This commit makes our build process emit application environment variables into
a Java file that's compiled together with the NativeAndroidRuntimeProvider
class, at the same time removing those variables from the native code so that
we don't set the variables twice (a performance optimization, nothing more).

Testing shows that startup hooks are properly called with only the DOTNET_STARTUP_HOOKS
variable set, which wasn't previously the case.

@grendello
grendello marked this pull request as ready for review January 23, 2026 12:52

@jonathanpeppersjonathanpeppers left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is there some existing native code that needs to be disabled for NativeAOT? that is packing and setting env vars at startup?

Comment threadsrc/Xamarin.Android.Build.Tasks/Resources/NativeAotRuntimeProvider.java Outdated
grendelloand others added 6 commits January 26, 2026 13:10
Fixes:
(_LintChecks target) -> obj\Release\android\src\net\dot\jni\nativeaot\NativeAotRuntimeProvider.java(16): warning XA0102: The indentation string here is different from on the previous line (" " vs \t) [SuspiciousIndentation]
@grendello

Copy link
Copy Markdown
ContributorAuthor

One timing test failed, irrelevant to the PR. Merging.

@grendello
grendello merged commit d8d567b into mainJan 26, 2026
1 of 2 checks passed
@grendello
grendello deleted the dev/grendel/naot-env branch January 26, 2026 14:49
jonathanpeppers pushed a commit that referenced this pull request Feb 4, 2026
…10709)
Fixes: #10705
When a `NativeAOT` application starts up, certain portions of the managed startup
sequence are executed on the shared library load but before the `JNI_OnLoad`
function is invoked by Android.
Both `MonoVM` and `CoreCLR` hosts set environment variables which may affect the
way the application behaves before they initialize the managed runtime. Those
variables are set from within native code, using data generated at application
build time.
Until now, the `NativeAOT` host followed suit, but it appears that we need to
set certain variables (e.g. those related to running the startup hooks) before
the shared library is loaded.
The only location where we can do it is the `NativeAndroidRuntimeProvider` Java
class which is responsible for, eventually, loading the application shared
library.
This commit makes our build process emit application environment variables into
a Java file that's compiled together with the `NativeAndroidRuntimeProvider`
class, at the same time removing those variables from the native code so that
we don't set the variables twice (a performance optimization, nothing more).
Testing shows that startup hooks are properly called with only the `DOTNET_STARTUP_HOOKS`
variable set, which wasn't previously the case.
jonathanpeppers added a commit that referenced this pull request Feb 4, 2026
…10709)
Fixes: #10705
When a \NativeAOT\ application starts up, certain portions of the managed startup
sequence are executed on the shared library load but before the \JNI_OnLoad\
function is invoked by Android.
Both \MonoVM\ and \CoreCLR\ hosts set environment variables which may affect the
way the application behaves before they initialize the managed runtime. Those
variables are set from within native code, using data generated at application
build time.
Until now, the \NativeAOT\ host followed suit, but it appears that we need to
set certain variables (e.g. those related to running the startup hooks) before
the shared library is loaded.
The only location where we can do it is the \NativeAndroidRuntimeProvider\ Java
class which is responsible for, eventually, loading the application shared
library.
This commit makes our build process emit application environment variables into
a Java file that's compiled together with the \NativeAndroidRuntimeProvider\
class, at the same time removing those variables from the native code so that
we don't set the variables twice (a performance optimization, nothing more).
Testing shows that startup hooks are properly called with only the \DOTNET_STARTUP_HOOKS\
variable set, which wasn't previously the case.
Co-authored-by: Jonathan Peppers <jonathan.peppers@microsoft.com>
jonathanpeppers added a commit that referenced this pull request Feb 5, 2026
…pp .so is loaded (#10768)
Backport of: #10709Fixes: #10705
When a `NativeAOT` application starts up, certain portions of the managed startup
sequence are executed on the shared library load but before the `JNI_OnLoad`
function is invoked by Android.
Both `MonoVM` and `CoreCLR` hosts set environment variables which may affect the
way the application behaves before they initialize the managed runtime. Those
variables are set from within native code, using data generated at application
build time.
Until now, the `NativeAOT` host followed suit, but it appears that we need to
set certain variables (e.g. those related to running the startup hooks) before
the shared library is loaded.
The only location where we can do it is the `NativeAndroidRuntimeProvider` Java
class which is responsible for, eventually, loading the application shared
library.
This commit makes our build process emit application environment variables into
a Java file that's compiled together with the `NativeAndroidRuntimeProvider`
class, at the same time removing those variables from the native code so that
we don't set the variables twice (a performance optimization, nothing more).
Testing shows that startup hooks are properly called with only the `DOTNET_STARTUP_HOOKS`
variable set, which wasn't previously the case.
Co-authored-by: Jonathan Peppers <jonathan.peppers@microsoft.com>
Co-authored-by: Marek Habersack <grendel@twistedcode.net>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Feb 26, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[NativeAOT] env var timing at startup

2 participants

@grendello@jonathanpeppers