diff --git a/src/mono/mono/metadata/native-library.c b/src/mono/mono/metadata/native-library.c
index b2d85270cd3fc0..164a3aef132f22 100644
--- a/src/mono/mono/metadata/native-library.c
+++ b/src/mono/mono/metadata/native-library.c
@@ -584,6 +584,40 @@ netcore_probe_for_module_nofail (MonoImage *image, const char *file_name, int fl
 	return result;
 }
 
+static MonoDl*
+netcore_lookup_self_native_handle (void)
+{
+	ERROR_DECL (load_error);
+	if (!internal_module)
+		internal_module = mono_dl_open_self (load_error);
+
+	if (!internal_module)
+		mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT, "DllImport error loading library '__Internal': '%s'.", mono_error_get_message_without_fields (load_error));
+
+	mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_DLLIMPORT, "Native library found via __Internal.");
+	mono_error_cleanup (load_error);
+
+	return internal_module;
+}
+
+static MonoDl* native_handle_lookup_wrapper (gpointer handle)
+{
+	MonoDl *result = NULL;
+
+	if (!internal_module)
+		netcore_lookup_self_native_handle ();
+
+	if (internal_module->handle == handle) {
+		result = internal_module;
+	} else {
+		native_library_lock ();
+		result = netcore_handle_lookup (handle);
+		native_library_unlock ();
+	}
+
+	return result;
+}
+
 static MonoDl *
 netcore_resolve_with_dll_import_resolver (MonoAssemblyLoadContext *alc, MonoAssembly *assembly, const char *scope, guint32 flags, MonoError *error)
 {
@@ -631,9 +665,7 @@ netcore_resolve_with_dll_import_resolver (MonoAssemblyLoadContext *alc, MonoAsse
 	mono_runtime_invoke_checked (resolve, NULL, args, error);
 	goto_if_nok (error, leave);
 
-	native_library_lock ();
-	result = netcore_handle_lookup (lib);
-	native_library_unlock ();
+	result = native_handle_lookup_wrapper (lib);
 
 leave:
 	HANDLE_FUNCTION_RETURN_VAL (result);
@@ -688,9 +720,7 @@ netcore_resolve_with_load (MonoAssemblyLoadContext *alc, const char *scope, Mono
 	mono_runtime_invoke_checked (resolve, NULL, args, error);
 	goto_if_nok (error, leave);
 
-	native_library_lock ();
-	result = netcore_handle_lookup (lib);
-	native_library_unlock ();
+	result = native_handle_lookup_wrapper (lib);
 
 leave:
 	HANDLE_FUNCTION_RETURN_VAL (result);
@@ -755,9 +785,7 @@ netcore_resolve_with_resolving_event (MonoAssemblyLoadContext *alc, MonoAssembly
 	mono_runtime_invoke_checked (resolve, NULL, args, error);
 	goto_if_nok (error, leave);
 
-	native_library_lock ();
-	result = netcore_handle_lookup (lib);
-	native_library_unlock ();
+	result = native_handle_lookup_wrapper (lib);
 
 leave:
 	HANDLE_FUNCTION_RETURN_VAL (result);
@@ -802,22 +830,6 @@ netcore_check_alc_cache (MonoAssemblyLoadContext *alc, const char *scope)
 	return result;
 }
 
-static MonoDl*
-netcore_lookup_self_native_handle (void)
-{
-	ERROR_DECL (load_error);
-	if (!internal_module)
-		internal_module = mono_dl_open_self (load_error);
-
-	if (!internal_module)
-		mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_DLLIMPORT, "DllImport error loading library '__Internal': '%s'.", mono_error_get_message_without_fields (load_error));
-
-	mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_DLLIMPORT, "Native library found via __Internal.");
-	mono_error_cleanup (load_error);
-
-	return internal_module;
-}
-
 static MonoDl *
 netcore_lookup_native_library (MonoAssemblyLoadContext *alc, MonoImage *image, const char *scope, guint32 flags)
 {
diff --git a/src/mono/mono/utils/mono-dl.c b/src/mono/mono/utils/mono-dl.c
index 512ce7205e606a..c4e5d5eafad243 100644
--- a/src/mono/mono/utils/mono-dl.c
+++ b/src/mono/mono/utils/mono-dl.c
@@ -176,8 +176,9 @@ fix_libc_name (const char *name)
  * mono_dl_open_self:
  * \param error pointer to MonoError
  *
- * Returns a handle to the main program, on android x86 it's not possible to
- * call dl_open(null), it returns a null handle, so this function returns RTLD_DEFAULT
+ * Returns a handle to the main program, on Android it's not possible to
+ * call dl_open(null) with RTLD_LAZY, it returns a null handle, so this
+ * function uses RTLD_NOW.
  * handle in this platform.
  * \p error points to MonoError where an error will be stored in
  * case of failure.   The error needs to be cleared when done using it, \c mono_error_cleanup.
@@ -195,7 +196,7 @@ mono_dl_open_self (MonoError *error)
 		return NULL;
 	}
 	mono_refcount_init (module, NULL);
-	module->handle = RTLD_DEFAULT;
+	module->handle = dlopen(NULL, RTLD_NOW);
 	module->dl_fallback = NULL;
 	module->full_name = NULL;
 	return module;
diff --git a/src/native/libs/System.Native/pal_dynamicload.c b/src/native/libs/System.Native/pal_dynamicload.c
index 6aaf70f50fcdd1..76f9c56678af5c 100644
--- a/src/native/libs/System.Native/pal_dynamicload.c
+++ b/src/native/libs/System.Native/pal_dynamicload.c
@@ -56,12 +56,6 @@ void SystemNative_FreeLibrary(void* handle)
     dlclose(handle);
 }
 
-#ifdef TARGET_ANDROID
-void* SystemNative_GetDefaultSearchOrderPseudoHandle(void)
-{
-    return (void*)RTLD_DEFAULT;
-}
-#else
 static void* volatile g_defaultSearchOrderPseudoHandle = NULL;
 void* SystemNative_GetDefaultSearchOrderPseudoHandle(void)
 {
@@ -69,11 +63,16 @@ void* SystemNative_GetDefaultSearchOrderPseudoHandle(void)
     void* defaultSearchOrderPseudoHandle = (void*)g_defaultSearchOrderPseudoHandle;
     if (defaultSearchOrderPseudoHandle == NULL)
     {
+#ifdef TARGET_ANDROID
+        int flag = RTLD_NOW;
+#else
+        int flag = RTLD_LAZY;
+#endif
+
         // Assign back to the static as well as the local here.
         // We don't need to check for a race between two threads as the value returned by
         // dlopen here will always be the same in a given environment.
-        g_defaultSearchOrderPseudoHandle = defaultSearchOrderPseudoHandle = dlopen(NULL, RTLD_LAZY);
+        g_defaultSearchOrderPseudoHandle = defaultSearchOrderPseudoHandle = dlopen(NULL, flag);
     }
     return defaultSearchOrderPseudoHandle;
 }
-#endif
diff --git a/src/tests/Interop/NativeLibrary/MainProgramHandle/MainProgramHandleTests.cs b/src/tests/Interop/NativeLibrary/MainProgramHandle/MainProgramHandleTests.cs
new file mode 100644
index 00000000000000..c526c2a8d2a0a4
--- /dev/null
+++ b/src/tests/Interop/NativeLibrary/MainProgramHandle/MainProgramHandleTests.cs
@@ -0,0 +1,46 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+using Xunit;
+
+public static class MainProgramHandleTests
+{
+    private static IntPtr s_handle;
+
+    static MainProgramHandleTests() => NativeLibrary.SetDllImportResolver(typeof(MainProgramHandleTests).Assembly,
+        (string libraryName, Assembly asm, DllImportSearchPath? dllImportSearchPath) =>
+        {
+            if (libraryName == "Self")
+            {
+                s_handle = NativeLibrary.GetMainProgramHandle();
+                Assert.NotEqual(IntPtr.Zero, s_handle);
+                return s_handle;
+            }
+
+            return IntPtr.Zero;
+        });
+
+    public static int Main()
+    {
+        try
+        {
+            free(s_handle);
+        }
+        catch (Exception e)
+        {
+            Console.WriteLine($"Test Failure: {e}");
+            return 101;
+        }
+
+        return 100;
+    }
+
+    [DllImport("Self")]
+    private static extern void free(IntPtr arg);
+}
diff --git a/src/tests/Interop/NativeLibrary/MainProgramHandle/MainProgramHandleTests.csproj b/src/tests/Interop/NativeLibrary/MainProgramHandle/MainProgramHandleTests.csproj
new file mode 100644
index 00000000000000..1ce6225d7853cd
--- /dev/null
+++ b/src/tests/Interop/NativeLibrary/MainProgramHandle/MainProgramHandleTests.csproj
@@ -0,0 +1,13 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+    <CLRTestTargetUnsupported Condition="'$(TargetsWindows)' == 'true' or '$(RuntimeVariant)' == 'monointerpreter'">true</CLRTestTargetUnsupported>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="MainProgramHandleTests.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="$(TestSourceDir)Common/CoreCLRTestLibrary/CoreCLRTestLibrary.csproj" />
+  </ItemGroup>
+</Project>
diff --git a/src/tests/issues.targets b/src/tests/issues.targets
index f39b00887245ec..e72474bad4bfac 100644
--- a/src/tests/issues.targets
+++ b/src/tests/issues.targets
@@ -2606,6 +2606,9 @@
         <ExcludeList Include = "$(XunitTestBinBase)/Interop/StructMarshalling/ReversePInvoke/MarshalSeqStruct/DelegatePInvoke/DelegatePInvokeTest/**">
             <Issue>needs triage</Issue>
         </ExcludeList>
+        <ExcludeList Include = "$(XunitTestBinBase)/Interop/NativeLibrary/MainProgramHandle/**">
+            <Issue>needs triage</Issue>
+        </ExcludeList>
         <ExcludeList Include = "$(XunitTestBinBase)/JIT/Methodical/eh/basics/throwinfilter_il_d/**">
             <Issue>https://github.com/dotnet/runtime/issues/47624</Issue>
         </ExcludeList>