diff --git a/build-tools/create-packs/Microsoft.Android.Runtime.proj b/build-tools/create-packs/Microsoft.Android.Runtime.proj
index 53db6c52f87..30172483af4 100644
--- a/build-tools/create-packs/Microsoft.Android.Runtime.proj
+++ b/build-tools/create-packs/Microsoft.Android.Runtime.proj
@@ -45,7 +45,7 @@ projects that use the Microsoft.Android.Runtimes framework in .NET 6+.
DependsOnTargets="_GetLicense;_GetDefaultPackageVersion"
BeforeTargets="GetFilesToPackage" >
- <_RuntimeFlavorDirName Condition=" '$(AndroidRuntime)' == 'CoreCLR' ">$(_CLRRuntimeFlavorDirName)
+ <_RuntimeFlavorDirName Condition=" '$(AndroidRuntime)' == 'CoreCLR' or '$(AndroidRuntime)' == 'NativeAOT' ">$(_CLRRuntimeFlavorDirName)
<_RuntimeFlavorDirName Condition=" '$(AndroidRuntime)' == 'Mono' Or '$(AndroidRuntime)' == '' ">$(_MonoRuntimeFlavorDirName)
<_ClangArch Condition=" '$(AndroidRID)' == 'android-arm64' ">aarch64
<_ClangArch Condition=" '$(AndroidRID)' == 'android-arm' ">arm
@@ -103,6 +103,10 @@ projects that use the Microsoft.Android.Runtimes framework in .NET 6+.
<_AndroidRuntimePackAssemblies Include="$(_MonoAndroidNETOutputRoot)$(AndroidLatestStableApiLevel)\Microsoft.Android.Runtime.NativeAOT.dll" />
+
+
+
+
diff --git a/src/Microsoft.Android.Runtime.NativeAOT/Android.Runtime.NativeAOT/DiagnosticSettings.cs b/src/Microsoft.Android.Runtime.NativeAOT/Android.Runtime.NativeAOT/DiagnosticSettings.cs
index 3731ec693c1..a3a3a411720 100644
--- a/src/Microsoft.Android.Runtime.NativeAOT/Android.Runtime.NativeAOT/DiagnosticSettings.cs
+++ b/src/Microsoft.Android.Runtime.NativeAOT/Android.Runtime.NativeAOT/DiagnosticSettings.cs
@@ -14,43 +14,6 @@ struct DiagnosticSettings {
public bool LogJniGlobalReferences;
private string? GrefPath;
- private TextWriter? GrefLrefLog;
-
-
- public TextWriter? GrefLog {
- get {
- if (!LogJniGlobalReferences) {
- return null;
- }
- return ((LrefPath != null && LrefPath == GrefPath)
- ? GrefLrefLog ??= CreateWriter (LrefPath)
- : null)
- ??
- ((GrefPath != null)
- ? CreateWriter (GrefPath)
- : null)
- ??
- new LogcatTextWriter (AndroidLogLevel.Debug, "NativeAot:GREF");
- }
- }
-
- public TextWriter? LrefLog {
- get {
- if (!LogJniLocalReferences) {
- return null;
- }
- return ((LrefPath != null && LrefPath == GrefPath)
- ? GrefLrefLog ??= CreateWriter (LrefPath)
- : null)
- ??
- ((LrefPath != null)
- ? CreateWriter (LrefPath)
- : null)
- ??
- new LogcatTextWriter (AndroidLogLevel.Debug, "NativeAot:LREF");
- }
- }
-
TextWriter? CreateWriter (string path)
{
try {
diff --git a/src/Microsoft.Android.Runtime.NativeAOT/Android.Runtime.NativeAOT/JavaInteropRuntime.cs b/src/Microsoft.Android.Runtime.NativeAOT/Android.Runtime.NativeAOT/JavaInteropRuntime.cs
index 5fed268de2f..a6554481986 100644
--- a/src/Microsoft.Android.Runtime.NativeAOT/Android.Runtime.NativeAOT/JavaInteropRuntime.cs
+++ b/src/Microsoft.Android.Runtime.NativeAOT/Android.Runtime.NativeAOT/JavaInteropRuntime.cs
@@ -13,8 +13,9 @@ static int JNI_OnLoad (IntPtr vm, IntPtr reserved)
{
try {
AndroidLog.Print (AndroidLogLevel.Info, "JavaInteropRuntime", "JNI_OnLoad()");
- LogcatTextWriter.Init ();
- return (int) JniVersion.v1_6;
+ AndroidCryptoNative_InitLibraryOnLoad(vm, reserved);
+ clr_initialize_on_onload(vm, reserved);
+ return (int)JniVersion.v1_6;
}
catch (Exception e) {
AndroidLog.Print (AndroidLogLevel.Error, "JavaInteropRuntime", $"JNI_OnLoad() failed: {e}");
@@ -22,7 +23,16 @@ static int JNI_OnLoad (IntPtr vm, IntPtr reserved)
}
}
- [UnmanagedCallersOnly (EntryPoint="JNI_OnUnload")]
+ [DllImport("*")]
+ static extern int AndroidCryptoNative_InitLibraryOnLoad (IntPtr vm, IntPtr reserved);
+
+ [DllImport("*")]
+ static extern int clr_initialize_on_onload (IntPtr vm, IntPtr reserved);
+
+ [DllImport("*")]
+ static extern int clr_initialize_on_runtime_init ();
+
+ [UnmanagedCallersOnly(EntryPoint = "JNI_OnUnload")]
static void JNI_OnUnload (IntPtr vm, IntPtr reserved)
{
AndroidLog.Print(AndroidLogLevel.Info, "JavaInteropRuntime", "JNI_OnUnload");
@@ -38,21 +48,20 @@ static void init (IntPtr jnienv, IntPtr klass, IntPtr classLoader)
var settings = new DiagnosticSettings ();
settings.AddDebugDotnetLog ();
- var typeManager = new ManagedTypeManager ();
var options = new NativeAotRuntimeOptions {
EnvironmentPointer = jnienv,
- ClassLoader = new JniObjectReference (classLoader),
- TypeManager = typeManager,
- ValueManager = new SimpleValueManager (),
+ ClassLoader = new JniObjectReference (classLoader, JniObjectReferenceType.Global),
+ TypeManager = new ManagedTypeManager (),
+ ValueManager = ManagedValueManager.GetOrCreateInstance (),
UseMarshalMemberBuilder = false,
- JniGlobalReferenceLogWriter = settings.GrefLog,
- JniLocalReferenceLogWriter = settings.LrefLog,
};
runtime = options.CreateJreVM ();
// Entry point into Mono.Android.dll
JNIEnvInit.InitializeJniRuntime (runtime);
+ clr_initialize_on_runtime_init ();
+
transition = new JniTransition (jnienv);
var handler = Java.Lang.Thread.DefaultUncaughtExceptionHandler;
diff --git a/src/Microsoft.Android.Runtime.NativeAOT/Android.Runtime.NativeAOT/Logging.cs b/src/Microsoft.Android.Runtime.NativeAOT/Android.Runtime.NativeAOT/Logging.cs
index 880e107e72f..be1911cf04e 100644
--- a/src/Microsoft.Android.Runtime.NativeAOT/Android.Runtime.NativeAOT/Logging.cs
+++ b/src/Microsoft.Android.Runtime.NativeAOT/Android.Runtime.NativeAOT/Logging.cs
@@ -8,51 +8,6 @@
namespace Microsoft.Android.Runtime;
-internal sealed class LogcatTextWriter : TextWriter {
-
- public static void Init ()
- {
- // This method is a no-op, but it's necessary to ensure the static
- // constructor is executed.
- }
-
- static LogcatTextWriter ()
- {
- Console.SetOut (new LogcatTextWriter (AndroidLogLevel.Info));
- Console.SetError (new LogcatTextWriter (AndroidLogLevel.Error));
- }
-
- AndroidLogLevel Level;
- string Tag;
-
- internal LogcatTextWriter (AndroidLogLevel level, string tag = "NativeAotFromAndroid")
- {
- Level = level;
- Tag = tag;
- }
-
- public override Encoding Encoding => Encoding.UTF8;
- public override string NewLine => "\n";
-
- public override void WriteLine (string? value)
- {
- if (value == null) {
- AndroidLog.Print (Level, Tag, "");
- return;
- }
- ReadOnlySpan span = value;
- while (!span.IsEmpty) {
- if (span.IndexOf ('\n') is int n && n < 0) {
- break;
- }
- var line = span.Slice (0, n);
- AndroidLog.Print (Level, Tag, line.ToString ());
- span = span.Slice (n + 1);
- }
- AndroidLog.Print (Level, Tag, span.ToString ());
- }
-}
-
static class AndroidLog {
[DllImport ("log", EntryPoint = "__android_log_print", CallingConvention = CallingConvention.Cdecl)]
diff --git a/src/Microsoft.Android.Runtime.NativeAOT/Java.Interop/JreRuntime.cs b/src/Microsoft.Android.Runtime.NativeAOT/Java.Interop/JreRuntime.cs
index ed4068094f1..49e8b8ff32d 100644
--- a/src/Microsoft.Android.Runtime.NativeAOT/Java.Interop/JreRuntime.cs
+++ b/src/Microsoft.Android.Runtime.NativeAOT/Java.Interop/JreRuntime.cs
@@ -28,9 +28,6 @@ class NativeAotRuntimeOptions : JniRuntime.CreationOptions {
public bool IgnoreUnrecognizedOptions {get; set;}
- public TextWriter? JniGlobalReferenceLogWriter {get; set;}
- public TextWriter? JniLocalReferenceLogWriter {get; set;}
-
public NativeAotRuntimeOptions ()
{
JniVersion = JniVersion.v1_2;
@@ -61,8 +58,8 @@ static NativeAotRuntimeOptions CreateJreVM (NativeAotRuntimeOptions builder)
builder.TypeManager ??= new ManagedTypeManager ();
#endif // NET
- builder.ValueManager ??= new SimpleValueManager ();
- builder.ObjectReferenceManager ??= new ManagedObjectReferenceManager (builder.JniGlobalReferenceLogWriter, builder.JniLocalReferenceLogWriter);
+ builder.ValueManager ??= ManagedValueManager.GetOrCreateInstance();
+ builder.ObjectReferenceManager ??= new Android.Runtime.AndroidObjectReferenceManager ();
if (builder.InvocationPointer != IntPtr.Zero || builder.EnvironmentPointer != IntPtr.Zero)
return builder;
diff --git a/src/Mono.Android/Android.Runtime/AndroidRuntime.cs b/src/Mono.Android/Android.Runtime/AndroidRuntime.cs
index 6945d6ad40f..b4f064548d6 100644
--- a/src/Mono.Android/Android.Runtime/AndroidRuntime.cs
+++ b/src/Mono.Android/Android.Runtime/AndroidRuntime.cs
@@ -102,7 +102,7 @@ public AndroidRuntimeOptions (IntPtr jnienv,
}
}
- class AndroidObjectReferenceManager : JniRuntime.JniObjectReferenceManager {
+ public class AndroidObjectReferenceManager : JniRuntime.JniObjectReferenceManager {
public override int GlobalReferenceCount {
get {return RuntimeNativeMethods._monodroid_gref_get ();}
}
diff --git a/src/Mono.Android/Android.Runtime/JNIEnvInit.cs b/src/Mono.Android/Android.Runtime/JNIEnvInit.cs
index f0c6947f8ee..9a1881f3e76 100644
--- a/src/Mono.Android/Android.Runtime/JNIEnvInit.cs
+++ b/src/Mono.Android/Android.Runtime/JNIEnvInit.cs
@@ -82,6 +82,10 @@ static Type TypeGetType (string typeName) =>
internal static void InitializeJniRuntime (JniRuntime runtime)
{
androidRuntime = runtime;
+ gref_gc_threshold = RuntimeNativeMethods._monodroid_max_gref_get ();
+ if (gref_gc_threshold != int.MaxValue) {
+ gref_gc_threshold = checked((gref_gc_threshold * 9) / 10);
+ }
SetSynchronizationContext ();
}
diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targets
index 208b2ba34ac..03b2cb1cb71 100644
--- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targets
+++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targets
@@ -18,7 +18,7 @@ This file contains the NativeAOT-specific MSBuild logic for .NET for Android.
true
true
-
+
<_IsPublishing Condition=" '$(_IsPublishing)' == '' ">true
@@ -55,7 +55,7 @@ This file contains the NativeAOT-specific MSBuild logic for .NET for Android.
@@ -68,6 +68,7 @@ This file contains the NativeAOT-specific MSBuild logic for .NET for Android.
<_NdkSysrootDir>$(_AndroidNdkDirectory)toolchains/llvm/prebuilt/$(_NdkPrebuiltAbi)/sysroot/usr/lib/$(_NdkSysrootAbi)/
<_NdkBinDir>$(_AndroidNdkDirectory)toolchains/llvm/prebuilt/$(_NdkPrebuiltAbi)/bin/
clang++
+ clang++
llvm-objcopy
@@ -110,6 +111,11 @@ This file contains the NativeAOT-specific MSBuild logic for .NET for Android.
+
+
+
+
+
diff --git a/src/native/clr/host/CMakeLists.txt b/src/native/clr/host/CMakeLists.txt
index 2409f846dae..69765d69fa0 100644
--- a/src/native/clr/host/CMakeLists.txt
+++ b/src/native/clr/host/CMakeLists.txt
@@ -25,6 +25,17 @@ string(TOLOWER ${CMAKE_BUILD_TYPE} XAMARIN_NET_ANDROID_SUFFIX)
set(XAMARIN_NET_ANDROID_LIB "net-android${CHECKED_BUILD_INFIX}.${XAMARIN_NET_ANDROID_SUFFIX}")
set(XAMARIN_NET_ANDROID_STATIC_LIB "${XAMARIN_NET_ANDROID_LIB}-static")
+set(XAMARIN_NET_ANDROID_NATIVEAOT_LIB "net-android-nativeaot${CHECKED_BUILD_INFIX}-${XAMARIN_NET_ANDROID_SUFFIX}")
+
+set(XAMARIN_NET_ANDROID_NATIVEAOT_SOURCES
+ bridge-processing.cc
+ gc-bridge.cc
+ internal-pinvokes.cc
+ os-bridge.cc
+ runtime-util.cc
+ xamarin_getifaddrs.cc
+)
+
set(XAMARIN_MONODROID_SOURCES
assembly-store.cc
bridge-processing.cc
@@ -72,6 +83,16 @@ if(BUILD_STATIC_LIBRARY)
)
endif()
+add_library(${XAMARIN_NET_ANDROID_NATIVEAOT_LIB}
+ STATIC
+ ${XAMARIN_NET_ANDROID_NATIVEAOT_SOURCES}
+)
+target_compile_definitions(
+ ${XAMARIN_NET_ANDROID_NATIVEAOT_LIB}
+ PRIVATE
+ NATIVEAOT
+)
+
macro(lib_target_options TARGET_NAME)
target_compile_definitions(
${TARGET_NAME}
@@ -156,11 +177,13 @@ macro(lib_target_options TARGET_NAME)
xa::lz4
-landroid
-llog
- -lcoreclr
)
endmacro ()
lib_target_options(${XAMARIN_NET_ANDROID_LIB})
+target_link_libraries(${XAMARIN_NET_ANDROID_LIB}
+ -lcoreclr
+)
xa_add_compile_definitions(${XAMARIN_NET_ANDROID_LIB})
xa_add_include_directories(${XAMARIN_NET_ANDROID_LIB})
@@ -175,3 +198,7 @@ if(BUILD_STATIC_LIBRARY)
xa_add_compile_definitions(${XAMARIN_NET_ANDROID_STATIC_LIB})
xa_add_include_directories(${XAMARIN_NET_ANDROID_STATIC_LIB})
endif()
+
+lib_target_options(${XAMARIN_NET_ANDROID_NATIVEAOT_LIB})
+xa_add_compile_definitions(${XAMARIN_NET_ANDROID_NATIVEAOT_LIB})
+xa_add_include_directories(${XAMARIN_NET_ANDROID_NATIVEAOT_LIB})
diff --git a/src/native/clr/host/bridge-processing.cc b/src/native/clr/host/bridge-processing.cc
index a72e75d902a..ec25cddc36c 100644
--- a/src/native/clr/host/bridge-processing.cc
+++ b/src/native/clr/host/bridge-processing.cc
@@ -14,6 +14,15 @@ void BridgeProcessing::initialize_on_runtime_init (JNIEnv *env, jclass runtimeCl
GCUserPeer_class = RuntimeUtil::get_class_from_runtime_field (env, runtimeClass, "mono_android_GCUserPeer", true);
GCUserPeer_ctor = env->GetMethodID (GCUserPeer_class, "", "()V");
+ GCUserPeerable_class = env->FindClass ("net/dot/jni/GCUserPeerable");
+ if (GCUserPeerable_class != nullptr) [[likely]] {
+ GCUserPeerable_class = static_cast(OSBridge::lref_to_gref (env, GCUserPeerable_class));
+ GCUserPeerable_jiAddManagedReference = env->GetMethodID (GCUserPeerable_class, "jiAddManagedReference", "(Ljava/lang/Object;)V");
+ GCUserPeerable_jiClearManagedReferences = env->GetMethodID (GCUserPeerable_class, "jiClearManagedReferences", "()V");
+ } else {
+ log_error (LOG_DEFAULT, "Failed to find net/dot/jni/GCUserPeerable class.");
+ }
+
abort_unless (GCUserPeer_class != nullptr && GCUserPeer_ctor != nullptr, "Failed to load mono.android.GCUserPeer!");
}
@@ -126,10 +135,10 @@ void BridgeProcessing::add_circular_references (const StronglyConnectedComponent
abort_unless (reference_added, [this, &prev, &next] {
jclass prev_java_class = env->GetObjectClass (prev.handle);
- const char *prev_class_name = Host::get_java_class_name_for_TypeManager (prev_java_class);
+ const char *prev_class_name = OSBridge::get_java_class_name_for_TypeManager (prev_java_class);
jclass next_java_class = env->GetObjectClass (next.handle);
- const char *next_class_name = Host::get_java_class_name_for_TypeManager (next_java_class);
+ const char *next_class_name = OSBridge::get_java_class_name_for_TypeManager (next_java_class);
return detail::_format_message (
"Failed to add reference between objects in a strongly connected component: %s -> %s.",
@@ -157,6 +166,11 @@ bool BridgeProcessing::add_reference (jobject from, jobject to) noexcept
abort_if_invalid_pointer_argument (from, "from");
abort_if_invalid_pointer_argument (to, "to");
+ if (GCUserPeerable_class != nullptr && env->IsInstanceOf (from, GCUserPeerable_class)) {
+ env->CallVoidMethod (from, GCUserPeerable_jiAddManagedReference, to);
+ return true;
+ }
+
jclass java_class = env->GetObjectClass (from);
jmethodID add_method_id = env->GetMethodID (java_class, "monodroidAddReference", "(Ljava/lang/Object;)V");
@@ -197,6 +211,11 @@ void BridgeProcessing::clear_references (jobject handle) noexcept
{
abort_if_invalid_pointer_argument (handle, "handle");
+ if (GCUserPeerable_class != nullptr && env->IsInstanceOf (handle, GCUserPeerable_class)) {
+ env->CallVoidMethod (handle, GCUserPeerable_jiClearManagedReferences);
+ return;
+ }
+
jclass java_class = env->GetObjectClass (handle);
jmethodID clear_method_id = env->GetMethodID (java_class, "monodroidClearReferences", "()V");
@@ -315,7 +334,7 @@ void BridgeProcessing::log_missing_add_references_method ([[maybe_unused]] jclas
return;
}
- char *class_name = Host::get_java_class_name_for_TypeManager (java_class);
+ char *class_name = OSBridge::get_java_class_name_for_TypeManager (java_class);
log_error (LOG_GC, "Missing monodroidAddReferences method for object of class {}", optional_string (class_name));
free (class_name);
#endif
@@ -331,7 +350,7 @@ void BridgeProcessing::log_missing_clear_references_method ([[maybe_unused]] jcl
return;
}
- char *class_name = Host::get_java_class_name_for_TypeManager (java_class);
+ char *class_name = OSBridge::get_java_class_name_for_TypeManager (java_class);
log_error (LOG_GC, "Missing monodroidClearReferences method for object of class {}", optional_string (class_name));
free (class_name);
#endif
diff --git a/src/native/clr/host/gc-bridge.cc b/src/native/clr/host/gc-bridge.cc
index 6bf3a387e96..0d16a5900f3 100644
--- a/src/native/clr/host/gc-bridge.cc
+++ b/src/native/clr/host/gc-bridge.cc
@@ -117,7 +117,7 @@ void GCBridge::log_handle_context (JNIEnv *env, HandleContext *ctx) noexcept
jobject handle = ctx->control_block->handle;
jclass java_class = env->GetObjectClass (handle);
if (java_class != nullptr) {
- char *class_name = Host::get_java_class_name_for_TypeManager (java_class);
+ char *class_name = OSBridge::get_java_class_name_for_TypeManager (java_class);
log_info (LOG_GC, "gref {:#x} [{}]", reinterpret_cast (handle), class_name);
free (class_name);
} else {
diff --git a/src/native/clr/host/host.cc b/src/native/clr/host/host.cc
index 5048d8eb32a..6db98b6aa1e 100644
--- a/src/native/clr/host/host.cc
+++ b/src/native/clr/host/host.cc
@@ -550,39 +550,6 @@ void Host::Java_mono_android_Runtime_register (JNIEnv *env, jstring managedType,
}
}
-auto Host::get_java_class_name_for_TypeManager (jclass klass) noexcept -> char*
-{
- if (klass == nullptr || Class_getName == nullptr) {
- return nullptr;
- }
-
- JNIEnv *env = OSBridge::ensure_jnienv ();
- jstring name = reinterpret_cast (env->CallObjectMethod (klass, Class_getName));
- if (name == nullptr) {
- log_error (LOG_DEFAULT, "Failed to obtain Java class name for object at {:p}", reinterpret_cast(klass));
- return nullptr;
- }
-
- const char *mutf8 = env->GetStringUTFChars (name, nullptr);
- if (mutf8 == nullptr) {
- log_error (LOG_DEFAULT, "Failed to convert Java class name to UTF8 (out of memory?)"sv);
- env->DeleteLocalRef (name);
- return nullptr;
- }
- char *ret = strdup (mutf8);
-
- env->ReleaseStringUTFChars (name, mutf8);
- env->DeleteLocalRef (name);
-
- char *dot = strchr (ret, '.');
- while (dot != nullptr) {
- *dot = '/';
- dot = strchr (dot + 1, '.');
- }
-
- return ret;
-}
-
auto Host::Java_JNI_OnLoad (JavaVM *vm, [[maybe_unused]] void *reserved) noexcept -> jint
{
jvm = vm;
diff --git a/src/native/clr/host/internal-pinvokes.cc b/src/native/clr/host/internal-pinvokes.cc
index 5260a6bac6a..a0334ffa3e8 100644
--- a/src/native/clr/host/internal-pinvokes.cc
+++ b/src/native/clr/host/internal-pinvokes.cc
@@ -9,6 +9,8 @@
using namespace xamarin::android;
+#define UNREACHABLE Helpers::abort_application (LOG_DEFAULT, "The method is not implemented. This is a stub and should not be called."sv)
+
int _monodroid_gref_get () noexcept
{
return OSBridge::get_gc_gref_count ();
@@ -31,13 +33,52 @@ void _monodroid_gref_log_delete (jobject handle, char type, const char *threadNa
const char* clr_typemap_managed_to_java (const char *typeName, const uint8_t *mvid) noexcept
{
+#ifdef NATIVEAOT
+ (void)typeName; // unused parameter
+ (void)mvid; // unused parameter
+ UNREACHABLE;
+ return nullptr;
+#else
return TypeMapper::managed_to_java (typeName, mvid);
+#endif
}
bool clr_typemap_java_to_managed (const char *java_type_name, char const** assembly_name, uint32_t *managed_type_token_id) noexcept
{
+#ifdef NATIVEAOT
+ (void)java_type_name; // unused parameter
+ (void)assembly_name; // unused parameter
+ (void)managed_type_token_id; // unused parameter
+ UNREACHABLE;
+ return false;
+#else
return TypeMapper::java_to_managed (java_type_name, assembly_name, managed_type_token_id);
+#endif
+}
+
+#ifdef NATIVEAOT
+void clr_initialize_on_onload (JavaVM *vm, void *reserved) noexcept
+{
+ (void)reserved; // unused parameter
+
+ JNIEnv *env = NULL;
+ vm->GetEnv ((void**)&env, JNI_VERSION_1_6);
+
+ OSBridge::initialize_on_onload (vm, env);
+ GCBridge::initialize_on_onload (env);
+
+ // AndroidSystem::init_max_gref_count ();
+}
+
+void clr_initialize_on_runtime_init () noexcept
+{
+ JNIEnv *env = OSBridge::ensure_jnienv ();
+ jclass runtimeClass = env->FindClass ("mono/android/Runtime");
+
+ OSBridge::initialize_on_runtime_init (env, runtimeClass);
+ GCBridge::initialize_on_runtime_init (env, runtimeClass);
}
+#endif
BridgeProcessingFtn clr_initialize_gc_bridge (
BridgeProcessingStartedFtn bridge_processing_started_callback,
@@ -81,7 +122,7 @@ void monodroid_log (LogLevel level, LogCategories category, const char *message)
char* monodroid_TypeManager_get_java_class_name (jclass klass) noexcept
{
- return Host::get_java_class_name_for_TypeManager (klass);
+ return OSBridge::get_java_class_name_for_TypeManager (klass);
}
void monodroid_free (void *ptr) noexcept
@@ -92,17 +133,36 @@ void monodroid_free (void *ptr) noexcept
const char*
_monodroid_lookup_replacement_type (const char *jniSimpleReference)
{
+#ifdef NATIVEAOT
+ (void)jniSimpleReference; // unused parameter
+ UNREACHABLE;
+ return nullptr;
+#else
return JniRemapping::lookup_replacement_type (jniSimpleReference);
+#endif
}
const JniRemappingReplacementMethod*
_monodroid_lookup_replacement_method_info (const char *jniSourceType, const char *jniMethodName, const char *jniMethodSignature)
{
+#ifdef NATIVEAOT
+ (void)jniSourceType; // unused parameter
+ (void)jniMethodName; // unused parameter
+ (void)jniMethodSignature; // unused parameter
+ UNREACHABLE;
+ return nullptr;
+#else
return JniRemapping::lookup_replacement_method_info (jniSourceType, jniMethodName, jniMethodSignature);
+#endif
}
managed_timing_sequence* monodroid_timing_start (const char *message)
{
+#ifdef NATIVEAOT
+ (void)message; // unused parameter
+ UNREACHABLE;
+ return nullptr;
+#else
// Technically a reference here is against the idea of shared pointers, but
// in this instance it's fine since we know we won't be storing the pointer
// and this way things are slightly faster.
@@ -117,10 +177,16 @@ managed_timing_sequence* monodroid_timing_start (const char *message)
}
ret->start = FastTiming::get_time ();
return ret;
+#endif
}
void monodroid_timing_stop (managed_timing_sequence *sequence, const char *message)
{
+#ifdef NATIVEAOT
+ (void)sequence; // unused parameter
+ (void)message; // unused parameter
+ UNREACHABLE;
+#else
constexpr std::string_view DEFAULT_MESSAGE { "Managed Timing" };
if (sequence == nullptr) {
return;
@@ -134,6 +200,7 @@ void monodroid_timing_stop (managed_timing_sequence *sequence, const char *messa
sequence->end = FastTiming::get_time ();
Timing::info (sequence, message == nullptr ? DEFAULT_MESSAGE.data () : message);
timing->release_sequence (sequence);
+#endif
}
void _monodroid_weak_gref_new (jobject curHandle, char curType, jobject newHandle, char newType, const char *threadName, int threadId, const char *from, int from_writable)
@@ -148,7 +215,12 @@ int _monodroid_weak_gref_get ()
int _monodroid_max_gref_get ()
{
+#ifdef NATIVEAOT
+ // FIXME
+ return 10000;
+#else
return static_cast(AndroidSystem::get_max_gref_count ());
+#endif
}
void _monodroid_weak_gref_delete (jobject handle, char type, const char *threadName, int threadId, const char *from, int from_writable)
@@ -178,13 +250,21 @@ void _monodroid_detect_cpu_and_architecture (uint16_t *built_for_cpu, uint16_t *
abort_if_invalid_pointer_argument (running_on_cpu, "running_on_cpu");
abort_if_invalid_pointer_argument (is64bit, "is64bit");
+#ifdef NATIVEAOT
+ UNREACHABLE;
+#else
bool _64bit;
monodroid_detect_cpu_and_architecture (*built_for_cpu, *running_on_cpu, _64bit);
*is64bit = _64bit;
+#endif
}
void* _monodroid_timezone_get_default_id ()
{
+#ifdef NATIVEAOT
+ UNREACHABLE;
+ return nullptr;
+#else
JNIEnv *env = OSBridge::ensure_jnienv ();
jmethodID getDefault = env->GetStaticMethodID (Host::get_java_class_TimeZone (), "getDefault", "()Ljava/util/TimeZone;");
jmethodID getID = env->GetMethodID (Host::get_java_class_TimeZone (), "getID", "()Ljava/lang/String;");
@@ -202,4 +282,5 @@ void* _monodroid_timezone_get_default_id ()
env->DeleteLocalRef (id);
env->DeleteLocalRef (d);
return def_id;
+#endif
}
diff --git a/src/native/clr/host/os-bridge.cc b/src/native/clr/host/os-bridge.cc
index 904ad36c523..d9f639f2ba8 100644
--- a/src/native/clr/host/os-bridge.cc
+++ b/src/native/clr/host/os-bridge.cc
@@ -28,6 +28,9 @@ void OSBridge::initialize_on_onload (JavaVM *vm, JNIEnv *env) noexcept
// weakrefClass != nullptr && weakrefCtor != nullptr && weakrefGet != nullptr,
// "Failed to look up required java.lang.ref.WeakReference members"
// );
+
+ jclass grefClass = env->FindClass ("java/lang/Class");
+ Class_getName = env->GetMethodID (grefClass, "getName", "()Ljava/lang/String;");
}
void OSBridge::initialize_on_runtime_init (JNIEnv *env, jclass runtimeClass) noexcept
@@ -419,3 +422,36 @@ void OSBridge::_monodroid_lref_log_delete (int lrefc, jobject handle, char type,
fflush (Logger::lref_log ());
}
+
+auto OSBridge::get_java_class_name_for_TypeManager (jclass klass) noexcept -> char*
+{
+ if (klass == nullptr || Class_getName == nullptr) {
+ return nullptr;
+ }
+
+ JNIEnv *env = ensure_jnienv ();
+ jstring name = reinterpret_cast (env->CallObjectMethod (klass, Class_getName));
+ if (name == nullptr) {
+ log_error (LOG_DEFAULT, "Failed to obtain Java class name for object at {:p}", reinterpret_cast(klass));
+ return nullptr;
+ }
+
+ const char *mutf8 = env->GetStringUTFChars (name, nullptr);
+ if (mutf8 == nullptr) {
+ log_error (LOG_DEFAULT, "Failed to convert Java class name to UTF8 (out of memory?)"sv);
+ env->DeleteLocalRef (name);
+ return nullptr;
+ }
+ char *ret = strdup (mutf8);
+
+ env->ReleaseStringUTFChars (name, mutf8);
+ env->DeleteLocalRef (name);
+
+ char *dot = strchr (ret, '.');
+ while (dot != nullptr) {
+ *dot = '/';
+ dot = strchr (dot + 1, '.');
+ }
+
+ return ret;
+}
diff --git a/src/native/clr/include/host/bridge-processing.hh b/src/native/clr/include/host/bridge-processing.hh
index 0fdb56d931e..f33b5e34b57 100644
--- a/src/native/clr/include/host/bridge-processing.hh
+++ b/src/native/clr/include/host/bridge-processing.hh
@@ -34,6 +34,10 @@ private:
static inline jclass GCUserPeer_class = nullptr;
static inline jmethodID GCUserPeer_ctor = nullptr;
+ static inline jclass GCUserPeerable_class = nullptr;
+ static inline jmethodID GCUserPeerable_jiAddManagedReference = nullptr;
+ static inline jmethodID GCUserPeerable_jiClearManagedReferences = nullptr;
+
void prepare_for_java_collection () noexcept;
void prepare_scc_for_java_collection (size_t scc_index, const StronglyConnectedComponent &scc) noexcept;
void take_weak_global_ref (const HandleContext &context) noexcept;
@@ -60,4 +64,6 @@ private:
void log_gref_delete (jobject handle) noexcept;
void log_weak_ref_delete (jobject weak) noexcept;
void log_gc_summary () noexcept;
+
+ static char* get_java_class_name (jclass klass) noexcept;
};
diff --git a/src/native/clr/include/host/host.hh b/src/native/clr/include/host/host.hh
index c1ae90788c2..2233e558b4c 100644
--- a/src/native/clr/include/host/host.hh
+++ b/src/native/clr/include/host/host.hh
@@ -21,8 +21,6 @@ namespace xamarin::android {
jobjectArray assembliesJava, jboolean isEmulator, jboolean haveSplitApks) noexcept;
static void Java_mono_android_Runtime_register (JNIEnv *env, jstring managedType, jclass nativeClass, jstring methods) noexcept;
- static auto get_java_class_name_for_TypeManager (jclass klass) noexcept -> char*;
-
static auto get_timing () -> std::shared_ptr
{
return _timing;
diff --git a/src/native/clr/include/host/os-bridge.hh b/src/native/clr/include/host/os-bridge.hh
index b9da49b07f9..93d9001659b 100644
--- a/src/native/clr/include/host/os-bridge.hh
+++ b/src/native/clr/include/host/os-bridge.hh
@@ -50,6 +50,8 @@ namespace xamarin::android {
return env;
}
+ static auto get_java_class_name_for_TypeManager (jclass klass) noexcept -> char*;
+
private:
static auto _monodroid_gref_inc () noexcept -> int;
static auto _monodroid_gref_dec () noexcept -> int;
@@ -60,6 +62,7 @@ namespace xamarin::android {
static inline JavaVM *jvm = nullptr;
static inline jclass GCUserPeer_class = nullptr;
static inline jmethodID GCUserPeer_ctor = nullptr;
+ static inline jmethodID Class_getName = nullptr;
static inline int gc_gref_count = 0;
static inline int gc_weak_gref_count = 0;
diff --git a/src/native/clr/include/runtime-base/internal-pinvokes.hh b/src/native/clr/include/runtime-base/internal-pinvokes.hh
index 0bc3f2d841f..b36aa79d3e4 100644
--- a/src/native/clr/include/runtime-base/internal-pinvokes.hh
+++ b/src/native/clr/include/runtime-base/internal-pinvokes.hh
@@ -15,6 +15,8 @@ extern "C" {
void _monodroid_gref_log_delete (jobject handle, char type, const char *threadName, int threadId, const char *from, int from_writable) noexcept;
const char* clr_typemap_managed_to_java (const char *typeName, const uint8_t *mvid) noexcept;
bool clr_typemap_java_to_managed (const char *java_type_name, char const** assembly_name, uint32_t *managed_type_token_id) noexcept;
+ void clr_initialize_on_onload (JavaVM *vm, void *reserved) noexcept;
+ void clr_initialize_on_runtime_init () noexcept;
BridgeProcessingFtn clr_initialize_gc_bridge (
BridgeProcessingStartedFtn bridge_processing_started_callback,
BridgeProcessingFinishedFtn mark_cross_references_callback) noexcept;
diff --git a/src/native/native.targets b/src/native/native.targets
index 0a8d197adc7..75fd7ecac4c 100644
--- a/src/native/native.targets
+++ b/src/native/native.targets
@@ -306,7 +306,6 @@
AndroidRID="%(AndroidSupportedTargetJitAbi.AndroidRID)"
AndroidRuntime="$(CMakeRuntimeFlavor)"
RuntimePackName="$(_RuntimePackName)" />
-
@@ -318,8 +317,17 @@
AndroidRID="%(AndroidSupportedTargetJitAbi.AndroidRID)"
AndroidRuntime="$(CMakeRuntimeFlavor)"
RuntimePackName="$(_RuntimePackName)" />
+ <_RuntimePackFiles Include="$(NativeRuntimeOutputRootDir)$(_RuntimeRedistDirName)\%(AndroidSupportedTargetJitAbi.AndroidRID)\*.o"
+ AndroidRID="%(AndroidSupportedTargetJitAbi.AndroidRID)"
+ AndroidRuntime="$(CMakeRuntimeFlavor)"
+ RuntimePackName="NativeAOT" />
+ <_RuntimePackFiles Include="$(NativeRuntimeOutputRootDir)$(_RuntimeRedistDirName)\%(AndroidSupportedTargetJitAbi.AndroidRID)\*.a"
+ AndroidRID="%(AndroidSupportedTargetJitAbi.AndroidRID)"
+ AndroidRuntime="$(CMakeRuntimeFlavor)"
+ RuntimePackName="NativeAOT" />
+