You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Avoid try/finally for keep-alive-only generated bindings #12314
dotnet/android main; generated C# bindings across supported target frameworks and runtimes.
Description
Generated C# bindings currently use a try/finally block even when the finally contains only GC.KeepAlive() calls for Java reference arguments. Exception-handling regions prevent RyuJIT from inlining otherwise-thin binding wrappers and add EH metadata/code size.
When no marshaling cleanup is required, the generator could instead emit:
The JNI invocation, storing any return value in a local.
GC.KeepAlive() for each managed argument that supplied a borrowed JNI handle.
The existing try/finally shape should remain whenever the generated method must delete local JNI references, dispose marshaler state, unpin memory, copy arrays back, or perform any other cleanup on exceptional exits.
This should be evaluated for generated C# bindings to Java APIs, including methods, properties, and constructors. The change should preserve argument and receiver lifetime guarantees related to #5405 across MonoVM, CoreCLR, and NativeAOT.
Validation should include generator expected-output tests, concurrent-GC lifetime stress coverage, exception-path coverage, and benchmarks or generated-IL/code-size comparisons demonstrating whether removing keep-alive-only EH regions enables useful inlining or otherwise reduces overhead.
Steps to Reproduce
Generate a C# binding method with a Java reference parameter that requires no temporary local-reference cleanup.
Inspect the generated method.
Observe that the JNI invocation is wrapped in try/finally solely to execute GC.KeepAlive(parameter).
Inspect the resulting IL/JIT diagnostics and observe the EH clause, which prevents method inlining.
Did you find any workaround?
Handwritten bindings can store the JNI result in a local, call GC.KeepAlive() after the invocation, and then return the result. There is no project-wide workaround for generated bindings.
Activity
[generator] Avoid keepalive-only finally blocks in generated bindings (…