Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/instructions/java-interop.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ Additional context for code under `external/Java.Interop/`. This complements the
- **`generator/`** — primary tool for generating C# bindings from Java API descriptions.
- **`class-parse/`** — parses Java `.class` files and generates API descriptions.
- **`java-source-utils/`** — utilities for processing Java source code.
- **`jcw-gen/`** — generates Java Callable Wrapper classes.
- Application Java Callable Wrappers are generated by `src/Microsoft.Android.Sdk.TrimmableTypeMap/`.
- **`param-name-importer/`** — imports parameter names from Java source.

### Supporting libraries
Expand Down
4 changes: 2 additions & 2 deletions .github/skills/tests/references/test-catalog.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ These tests can be run immediately with `dotnet test` on the `.csproj`, even if
| **java source** | `external/Java.Interop/tests/Java.Interop.Tools.JavaSource-Tests/` | `dotnet test external/Java.Interop/tests/Java.Interop.Tools.JavaSource-Tests/Java.Interop.Tools.JavaSource-Tests.csproj -v minimal` |
| **maven** | `external/Java.Interop/tests/Java.Interop.Tools.Maven-Tests/` | `dotnet test external/Java.Interop/tests/Java.Interop.Tools.Maven-Tests/Java.Interop.Tools.Maven-Tests.csproj -v minimal` |
| **api xml adjuster** | `external/Java.Interop/tests/Xamarin.Android.Tools.ApiXmlAdjuster-Tests/` | `dotnet test external/Java.Interop/tests/Xamarin.Android.Tools.ApiXmlAdjuster-Tests/Xamarin.Android.Tools.ApiXmlAdjuster-Tests.csproj -v minimal` |
| **java callable wrappers** | `external/Java.Interop/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/` | `dotnet test external/Java.Interop/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/Java.Interop.Tools.JavaCallableWrappers-Tests.csproj -v minimal` |
| **Java peer naming/scanning** | `external/Java.Interop/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/` | `dotnet test external/Java.Interop/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/Java.Interop.Tools.JavaCallableWrappers-Tests.csproj -v minimal` |
| **java type system** | `external/Java.Interop/tests/Java.Interop.Tools.JavaTypeSystem-Tests/` | `dotnet test external/Java.Interop/tests/Java.Interop.Tools.JavaTypeSystem-Tests/Java.Interop.Tools.JavaTypeSystem-Tests.csproj -v minimal` |
| **expressions** | `external/Java.Interop/tests/Java.Interop.Tools.Expressions-Tests/` | `dotnet test external/Java.Interop/tests/Java.Interop.Tools.Expressions-Tests/Java.Interop.Tools.Expressions-Tests.csproj -v minimal` ⚠️ Requires `javac` |
| **generator tools** | `external/Java.Interop/tests/Java.Interop.Tools.Generator-Tests/` | `dotnet test external/Java.Interop/tests/Java.Interop.Tools.Generator-Tests/Java.Interop.Tools.Generator-Tests.csproj -v minimal` |
Expand Down Expand Up @@ -198,7 +198,7 @@ cause, or stack-trace extraction fails, while borrowed references remain valid.
| Test Area | Assembly / Project | Notes |
|-----------|--------------------|-------|
| **generator** | `external/Java.Interop/tests/generator-Tests/` | Binding generator tests |
| **java callable wrappers** | `external/Java.Interop/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/` | JCW generation |
| **Java peer naming/scanning** | `external/Java.Interop/tests/Java.Interop.Tools.JavaCallableWrappers-Tests/` | Naming, scanning, and type-name mapping; current JCW generation is covered by the trimmable type map suites |
| **java type system** | `external/Java.Interop/tests/Java.Interop.Tools.JavaTypeSystem-Tests/` | Java type system tooling |
| **java source** | `external/Java.Interop/tests/Java.Interop.Tools.JavaSource-Tests/` | Java source generation |
| **maven** | `external/Java.Interop/tests/Java.Interop.Tools.Maven-Tests/` | Maven integration |
Expand Down
30 changes: 30 additions & 0 deletions Documentation/guides/internals/JavaJNI_Interop.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,27 @@ The main outputs are:

The app build also generates needed **platform JCWs** from framework inputs alongside user JCWs: for example, the [build tests](../../../src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/TrimmableTypeMapBuildTests.cs) check for `typemap/java/android/app/ActivityTracker.java` and its `Runtime.registerNatives` call. The [reference pack](../../../build-tools/create-packs/Microsoft.Android.Ref.proj) no longer ships prebuilt `mono.android.jar` or `mono.android.dex`. The handwritten Java runtime support instead comes from `java_runtime_trimmable.jar`, selected by [`_CollectRuntimeJarFilenames`](../../../src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets); this is not a jar of pre-generated platform JCWs. `ApplicationRegistration.java` is generated separately during the app build.

The .NET 12 cleanup retires the standalone `jcw-gen` tool and the legacy public
JCW emitter in `Java.Interop.Tools.JavaCallableWrappers`: its `CallableWrapper*`
model/writers, reader/writer options, `JavaPeerStyle`, method classifier, and
Cecil/XML import/export adapters. That emitter produced `__md_methods`,
Comment on lines +85 to +88
`Runtime.register`, and `TypeManager.Activate` references whose runtime
implementations had already been removed. The assembly's shared naming,
scanning, hashing, and type-name mapping utilities remain available, as does
the supported XAJavaInterop1 **C# binding** generator. Application JCWs are
generated exclusively by the trimmable pipeline.

The SDK likewise ships only `java_runtime_trimmable.jar` and its DEX companion.
The unused `java_runtime`, `java_runtime_fastdev`, `java_runtime_clr`, and
`java_runtime_fastdev_clr` artifact pairs, Java `DebugRuntime`/`BuildConfig`
classes, and old environment placeholder are retired. `Runtime.init`,
`createNewContext`, `createNewContextWithData`, `switchToContext`,
`destroyContexts`, `MonoPackageManager.setContext`, and `getDependencies`
are no longer supplied. These are intentional tooling/bootstrap compatibility
removals; custom build tools and Java sources must use the retained runtime
artifact and current startup path. `Runtime.initInternal`, `registerNatives`,
GC peers, and `ApplicationRegistration.Context` remain live.

Each per-assembly TypeMap contains assembly-level mapping attributes: a key such as `my/app/MainActivity`, a proxy type, and, for a trimmable mapping, the managed target type. The root references the per-assembly maps via `TypeMapAssemblyTargetAttribute<T>`. The emitter writes **IL and metadata**, not `.cs` files; the C# in the sections below is an explanatory translation of emitted code, not a file that a developer should edit. See [`TypeMapAssemblyGenerator`](../../../src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/TypeMapAssemblyGenerator.cs), [`TypeMapAssemblyEmitter.EmitTypeMapAttribute`](../../../src/Microsoft.Android.Sdk.TrimmableTypeMap/Generator/TypeMapAssemblyEmitter.cs), and the [build-pipeline guide](../../../src/Microsoft.Android.Sdk.TrimmableTypeMap/README.md).

For the example Activity, think of a mapping like this **conceptual C#**:
Expand Down Expand Up @@ -122,6 +143,15 @@ When JNI returns an object or Java passes one into managed code, [`TrimmableType

The generated Java `onCreate` calls its native `n_OnCreate_Landroid_os_Bundle_`; constructors similarly declare generated `nctor_*` native callbacks, and instantiate/activate the managed peer when appropriate. The class's static block calls `mono.android.Runtime.registerNatives (MainActivity.class)` when the class is first initialized. This is **per Java class**. Application and instrumentation JCWs instead use a guarded `__md_registerNatives()` helper called from their generated wrappers: registration in their static initializer can be too early in startup. The declaration of `registerNatives(Class)` in [`mono.android.Runtime`](../../../src/java-runtime/java/mono/android/Runtime.java) is handwritten Java; individual JCWs and their registration calls are generated.

Abstract JCWs retain their Java constructors and `super(...)` calls for
subclasses, but do not declare or call native constructor bridges. Deferred
Application/Instrumentation hierarchies also omit those bridges and their
unused managed UCO constructor registrations; managed `CreateInstance`
activation remains available. A deferred class with no non-constructor
callbacks needs no lazy registration helper or flag. Callback-bearing
deferred classes still use the helper, and nonempty native registration,
concrete constructor guards, GC hooks, and startup registration remain intact.

There is no concatenated `__md_methods` string and no `Runtime.register("managed.Type, Assembly", ...)` registration in this path. The old JNI native-symbol mangling rules (`Java_package_Class_method...`) matter for symbol-lookup-based JNI code, but generated app JCW callbacks here are associated with their Java declarations through [`RegisterNatives`](https://docs.oracle.com/en/java/javase/17/docs/specs/jni/functions.html#registernatives): the Java method **name** and **signature** must match; no `Java_...` export is required for each method.

### Runtime startup and registration handshake
Expand Down
1 change: 0 additions & 1 deletion Microsoft.Android.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,6 @@
<Project Path="external/Java.Interop/src/Xamarin.Android.Tools.ApiXmlAdjuster/Xamarin.Android.Tools.ApiXmlAdjuster.csproj" />
<Project Path="external/Java.Interop/tools/class-parse/class-parse.csproj" />
<Project Path="external/Java.Interop/tools/java-source-utils/java-source-utils.csproj" />
<Project Path="external/Java.Interop/tools/jcw-gen/jcw-gen.csproj" />
<Project Path="tools/relnote-gen/relnote-gen.csproj" />
<Project Path="tools/tmt/tmt.csproj">
<Platform Solution="*|Any CPU" Project="anycpu" />
Expand Down
8 changes: 0 additions & 8 deletions build-tools/installers/create-installers.targets
Original file line number Diff line number Diff line change
Expand Up @@ -58,16 +58,8 @@
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)NuGet.Versioning.dll" />
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)r8.jar" />
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)bundletool.jar" />
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java_runtime.jar" />
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java_runtime_fastdev.jar" />
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java_runtime_trimmable.jar" />
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java_runtime.dex" />
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java_runtime_fastdev.dex" />
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java_runtime_trimmable.dex" />
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java_runtime_clr.jar" />
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java_runtime_fastdev_clr.jar" />
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java_runtime_clr.dex" />
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)java_runtime_fastdev_clr.dex" />
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)manifestmerger.jar" />
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)proguard-android-optimize.txt" />
<_MSBuildFiles Include="$(MicrosoftAndroidSdkOutDir)proguard-android.txt" />
Expand Down
6 changes: 3 additions & 3 deletions build-tools/scripts/Jar.targets
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@
</Target>
<Target Name="_GetJavaRuntimeJarPath">
<PropertyGroup>
<_RuntimeJar_InTree>$([System.IO.Path]::GetFullPath ('$(XAInstallPrefix)'))\xbuild\Xamarin\Android\java_runtime.jar</_RuntimeJar_InTree>
<_RuntimeJar_System Condition=" '$(_XamarinAndroidMSBuildDirectory)' != '' ">$(_XamarinAndroidMSBuildDirectory)\java_runtime.jar</_RuntimeJar_System>
<_RuntimeJar_InTree>$([System.IO.Path]::GetFullPath ('$(XAInstallPrefix)'))\xbuild\Xamarin\Android\java_runtime_trimmable.jar</_RuntimeJar_InTree>
<_RuntimeJar_System Condition=" '$(_XamarinAndroidMSBuildDirectory)' != '' ">$(_XamarinAndroidMSBuildDirectory)\java_runtime_trimmable.jar</_RuntimeJar_System>
<_JavaRuntimeJarPath Condition=" Exists($(_RuntimeJar_InTree)) ">$(_RuntimeJar_InTree)</_JavaRuntimeJarPath>
<_JavaRuntimeJarPath Condition=" '$(_JavaRuntimeJarPath)' == '' and Exists($(_RuntimeJar_System)) ">$(_RuntimeJar_System)</_JavaRuntimeJarPath>
</PropertyGroup>
<Error
Condition=" '$(_JavaRuntimeJarPath)' == '' "
Text="Could not determine path to `java_runtime.jar`."
Text="Could not determine path to `java_runtime_trimmable.jar`."
/>
</Target>
<Target Name="BuildTestJarFile"
Expand Down
2 changes: 1 addition & 1 deletion external/Java.Interop/Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
<!--
Microsoft.SourceLink.GitHub is a build-time only package (PrivateAssets="All"), but its
dependency Microsoft.Build.Tasks.Git 10.0.300 pulls System.IO.Hashing 10.0.8 in as a *runtime*
asset. Projects that only reference System.IO.Hashing transitively (e.g. class-parse, jcw-gen,
asset. Projects that only reference System.IO.Hashing transitively (e.g. class-parse,
generator) therefore ship a System.IO.Hashing 10.0.8 assembly, which collides in the shared
.NET for Android SDK pack `tools/` directory with the $(SystemIOHashingPackageVersion) assembly the
build tasks are compiled against (System.IO.Hashing bumps its AssemblyVersion every patch),
Expand Down
1 change: 0 additions & 1 deletion external/Java.Interop/Java.Interop.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@
<Project Path="tools/class-parse/class-parse.csproj" />
<Project Path="tools/generator/generator.csproj" />
<Project Path="tools/java-source-utils/java-source-utils.csproj" />
<Project Path="tools/jcw-gen/jcw-gen.csproj" />
<Project Path="tools/param-name-importer/param-name-importer.csproj" />
</Folder>
</Solution>

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -316,27 +316,6 @@ The following terms should not be translated: Metadata.xml, path.</comment>
<value>JNI signature override '{0}' is invalid or does not match the parameter count for member '{1}'.</value>
<comment>{0} - JNI method signature. {1} - .NET member.</comment>
</data>
<data name="JavaCallableWrappers_XA4200" xml:space="preserve">
<value>Cannot generate Java wrapper for type '{0}'. Only 'class' types are supported.</value>
<comment>{0} - Java type.
The following terms should not be translated:
class.</comment>
</data>
<data name="JavaCallableWrappers_XA4201" xml:space="preserve">
<value>Cannot determine JNI name for type '{0}'.</value>
<comment>{0} - Java type.
The following terms should not be translated: JNI.</comment>
</data>
<data name="JavaCallableWrappers_XA4203" xml:space="preserve">
<value>The 'Name' property must be a fully qualified type like 'com.example.MyClass' and no package was found for '{0}'.</value>
<comment>{0} - Java type.
The following terms should not be translated:
Name, com.example.MyClass.</comment>
</data>
<data name="JavaCallableWrappers_XA4204" xml:space="preserve">
<value>Unable to resolve interface type '{0}'. Are you missing an assembly reference?</value>
<comment>{0} - Java interface.</comment>
</data>
<data name="JavaCallableWrappers_XA4205" xml:space="preserve">
<value>[ExportField] can only be used on methods with 0 parameters.</value>
<comment>The following terms should not be translated: [ExportField].</comment>
Expand All @@ -353,10 +332,6 @@ Name, com.example.MyClass.</comment>
<value>[ExportField] cannot be used on a method returning 'void'.</value>
<comment>The following terms should not be translated: [ExportField], void.</comment>
</data>
<data name="JavaCallableWrappers_XA4217" xml:space="preserve">
<value>Cannot override Kotlin-generated method '{0}' because it is not a valid Java method name. This method can only be overridden from Kotlin.</value>
<comment>{0} - Kotlin method name.</comment>
</data>
<data name="JniMarshalMethodGen_JM4001" xml:space="preserve">
<value>Unable to preload reference '{0}'.</value>
<comment>{0} - assembly path</comment>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,6 @@ namespace Java.Interop.Tools.Diagnostics {
// XA4110 The registrar cannot marshal the out parameter of type `{0}` in signature for method `{1}`.
// XA4111 The registrar cannot build a signature for type `{0}' in method `{1}`.
// XA42xx ACW generation
// XA4200 Can only generate ACW's for `claas` types.
// XA4201 Unable to determine JNI name for type {0}.
// XA4203 The specified type name must be fully qualified.
// XA4204 Unable to resolve interface type '{0}'. Are you missing an assembly reference?
// XA4205 [ExportField] can only be used on methods with 0 parameters.
// XA4206 [Export] cannot be used on a generic type.
// XA4207 [ExportField] cannot be used on a generic type.
Expand All @@ -103,7 +99,6 @@ namespace Java.Interop.Tools.Diagnostics {
// XA4210 "You need to add a reference to Mono.Android.Export.dll when you use ExportAttribute or ExportFieldAttribute."
// XA4211 AndroidManifest.xml //uses-sdk/@android:targetSdkVersion '{0}' is less than $(TargetFrameworkVersion) '{1}'. Using API-{1} for ACW compilation.
// XA4212 Type `{0}` implements `Android.Runtime.IJavaObject` but does not inherit `Java.Lang.Object` or `Java.Lang.Throwable`. This is not supported.
// XA4217 Cannot override Kotlin-generated method '{0}' because it is not a valid Java method name. This method can only be overridden from Kotlin."
// XA5xxx GCC and toolchain
// XA32xx .apk generation
// XA4300 Unsupported $(AndroidSupportedAbis) value '{0}'; ignoring.
Expand Down Expand Up @@ -195,4 +190,3 @@ public static Action<TraceLevel, string> CreateConsoleLogger ()
}
}
}

Loading
Loading