This repository was archived by the owner on Aug 27, 2026. It is now read-only.

[generator] Don't avoid blittable types for fields - #1353

Merged
jonathanpeppers merged 2 commits into
dotnet:mainfrom
jonpryor:dev/jonpryor/jonp-field-SetValue-boolean
Aug 12, 2025
Merged

[generator] Don't avoid blittable types for fields#1353
jonathanpeppers merged 2 commits into
dotnet:mainfrom
jonpryor:dev/jonpryor/jonp-field-SetValue-boolean

Conversation

@jonpryor

Copy link
Copy Markdown
Contributor

Fixes: dotnet/android#10404

Context: 57f7bc8

Commit 57f7bc8 updated generator to "avoid non-blittable types" in native callback methods, for which there were two non-blittables:

  • System.Boolean, which should be marshaled as a System.SByte, and
  • System.Char, which should be marshaled as a System.UInt16.

The problem is that this hit a codepath which was not "for native callback methods": field bindings.

Consider android.widget.RelativeLayout.LayoutParams.alignWithParent:

package android.widget;
public /* partial */ class RelativeLayout {
public /* partial */ class LayoutParams {
public boolean alignWithParent;
}
}

which is bound as RelativeLayout.LayoutParams.AlignWithParent:

namespace Android.Widget;
public partial class RelativeLayout {
public new partial class LayoutParams {
[Register]
public bool AlignWithParent {
get => _members.InstanceFields.GetBooleanValue ("alignWithParent.Z", this);
set {
_members.InstanceFields.SetValue("alignWithParent.Z", this, value ? (sbyte)1 : (sbyte)0);
}
}
}
}

The problem is the property setter, which calls
Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, sbyte). Before 57f7bc8, it would instead call
Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, bool), but with 57f7bc8 there are now runtime crashes when boolean fields are accessed, starting in .NET 10 Preview 2.

The following code fragment:

var p = new RelativeLayout.LayoutParams (1, 2) {
AlignWithParent = true,
};

crashes with:

F droid_boolfiel: java_vm_ext.cc:542] JNI DETECTED ERROR IN APPLICATION: attempt to access field boolean android.widget.RelativeLayout$LayoutParams.alignWithParent of type boolean with the wrong type byte: 0x709385d8
F droid_boolfiel: java_vm_ext.cc:542] in call to SetByteField
F droid_boolfiel: java_vm_ext.cc:542] from void crc6463d68d2626be2acb.MainActivity.n_onCreate(android.os.Bundle)

Fix this by updating generator so that BoundFieldAsProperty.cs uses the parameter as-is when ISymbol.OnlyFormatOnMarshal=true.

The binding for RelativeLayout.LayoutParams.AlignWithParent becomes:

namespace Android.Widget;
public partial class RelativeLayout {
public new partial class LayoutParams {
[Register]
public bool AlignWithParent {
get => _members.InstanceFields.GetBooleanValue ("alignWithParent.Z", this);
set {
_members.InstanceFields.SetValue("alignWithParent.Z", this, value);
}
}
}
}

i.e. calling JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, bool).

Fixes: dotnet/android#10404
Context: 57f7bc8
Commit 57f7bc8 updated `generator` to "avoid non-blittable types"
in native callback methods, for which there were two non-blittables:
* System.Boolean, which should be marshaled as a System.SByte, and
* System.Char, which should be marshaled as a System.UInt16.
The problem is that this hit a codepath which was *not*
"for native callback methods": field bindings.
Consider [`android.widget.RelativeLayout.LayoutParams.alignWithParent`][0]:
package android.widget;
public /* partial */ class RelativeLayout {
public /* partial */ class LayoutParams {
public boolean alignWithParent;
}
}
which is bound as [`RelativeLayout.LayoutParams.AlignWithParent`][1]:
namespace Android.Widget;
public partial class RelativeLayout {
public new partial class LayoutParams {
[Register]
public bool AlignWithParent {
get => _members.InstanceFields.GetBooleanValue ("alignWithParent.Z", this);
set {
_members.InstanceFields.SetValue("alignWithParent.Z", this, value ? (sbyte)1 : (sbyte)0);
}
}
}
}
The problem is the property setter, which calls
`Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, sbyte)`.
Before 57f7bc8, it would instead call
`Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, bool)`,
but with 57f7bc8 there are now runtime crashes when boolean fields
are accessed, starting in .NET 10 Preview 2.
The following code fragment:
var p = new RelativeLayout.LayoutParams (1, 2) {
AlignWithParent = true,
};
crashes with:
F droid_boolfiel: java_vm_ext.cc:542] JNI DETECTED ERROR IN APPLICATION: attempt to access field boolean android.widget.RelativeLayout$LayoutParams.alignWithParent of type boolean with the wrong type byte: 0x709385d8
F droid_boolfiel: java_vm_ext.cc:542] in call to SetByteField
F droid_boolfiel: java_vm_ext.cc:542] from void crc6463d68d2626be2acb.MainActivity.n_onCreate(android.os.Bundle)
Fix this by updating `generator` so that `BoundFieldAsProperty.cs`
uses the parameter as-is when `ISymbol.OnlyFormatOnMarshal`=true.
The binding for `RelativeLayout.LayoutParams.AlignWithParent` becomes:
namespace Android.Widget;
public partial class RelativeLayout {
public new partial class LayoutParams {
[Register]
public bool AlignWithParent {
get => _members.InstanceFields.GetBooleanValue ("alignWithParent.Z", this);
set {
_members.InstanceFields.SetValue("alignWithParent.Z", this, value);
}
}
}
}
i.e. calling `JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, bool)`.
[0]: https://developer.android.com/reference/android/widget/RelativeLayout.LayoutParams#alignWithParent
[1]: https://learn.microsoft.com/en-us/dotnet/api/android.widget.relativelayout.layoutparams.alignwithparent?view=net-android-34.0

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull Request Overview

This PR fixes a runtime crash in .NET 10 Preview 2 where boolean field setters were calling the wrong JNI method due to an unintended side effect of commit 57f7bc8. The issue occurred when the generator's "avoid non-blittable types" logic, intended for native callback methods, was incorrectly applied to field bindings.

  • Fixes field property setters to use the correct parameter type instead of converting to native types
  • Restores proper boolean field handling by preserving the original parameter when OnlyFormatOnMarshal is true
  • Adds test coverage for boolean and char field bindings to prevent regression

Reviewed Changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
FileDescription
tools/generator/SourceWriters/BoundFieldAsProperty.csCore fix - conditionally preserve parameter type for field setters when OnlyFormatOnMarshal is true
tests/generator-Tests/expected.xaji/StaticFields/Xamarin.Test.SomeObject.csTest output showing corrected static boolean/char field property generation
tests/generator-Tests/expected.xaji/NonStaticFields/Xamarin.Test.SomeObject.csTest output showing corrected instance boolean/char field property generation
tests/generator-Tests/expected.ji/StaticFields/Xamarin.Test.SomeObject.csTest output for Java.Interop target showing corrected static field generation
tests/generator-Tests/expected.ji/StaticFields/StaticField.xmlTest metadata defining boolean and char fields for static field tests
tests/generator-Tests/expected.ji/NonStaticFields/Xamarin.Test.SomeObject.csTest output for Java.Interop target showing corrected instance field generation
tests/generator-Tests/expected.ji/NonStaticFields/NonStaticField.xmlTest metadata defining boolean and char fields for instance field tests

@jonathanpeppers
jonathanpeppers enabled auto-merge (squash) August 12, 2025 18:44
@jonathanpeppers
jonathanpeppers merged commit 90ac202 into dotnet:mainAug 12, 2025
2 checks passed
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Sep 12, 2025
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.

JNI DETECTED ERROR IN APPLICATION around accessing boolean fields

4 participants

@jonpryor@grendello@jonathanpeppers
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
This repository was archived by the owner on Aug 27, 2026. It is now read-only.

[generator] Don't avoid blittable types for fields - #1353

Merged
jonathanpeppers merged 2 commits into
dotnet:mainfrom
jonpryor:dev/jonpryor/jonp-field-SetValue-boolean
Aug 12, 2025
Merged

[generator] Don't avoid blittable types for fields#1353
jonathanpeppers merged 2 commits into
dotnet:mainfrom
jonpryor:dev/jonpryor/jonp-field-SetValue-boolean

Conversation

@jonpryor

Copy link
Copy Markdown
Contributor

Fixes: dotnet/android#10404

Context: 57f7bc8

Commit 57f7bc8 updated generator to "avoid non-blittable types" in native callback methods, for which there were two non-blittables:

  • System.Boolean, which should be marshaled as a System.SByte, and
  • System.Char, which should be marshaled as a System.UInt16.

The problem is that this hit a codepath which was not "for native callback methods": field bindings.

Consider android.widget.RelativeLayout.LayoutParams.alignWithParent:

package android.widget;
public /* partial */ class RelativeLayout {
public /* partial */ class LayoutParams {
public boolean alignWithParent;
}
}

which is bound as RelativeLayout.LayoutParams.AlignWithParent:

namespace Android.Widget;
public partial class RelativeLayout {
public new partial class LayoutParams {
[Register]
public bool AlignWithParent {
get => _members.InstanceFields.GetBooleanValue ("alignWithParent.Z", this);
set {
_members.InstanceFields.SetValue("alignWithParent.Z", this, value ? (sbyte)1 : (sbyte)0);
}
}
}
}

The problem is the property setter, which calls
Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, sbyte). Before 57f7bc8, it would instead call
Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, bool), but with 57f7bc8 there are now runtime crashes when boolean fields are accessed, starting in .NET 10 Preview 2.

The following code fragment:

var p = new RelativeLayout.LayoutParams (1, 2) {
AlignWithParent = true,
};

crashes with:

F droid_boolfiel: java_vm_ext.cc:542] JNI DETECTED ERROR IN APPLICATION: attempt to access field boolean android.widget.RelativeLayout$LayoutParams.alignWithParent of type boolean with the wrong type byte: 0x709385d8
F droid_boolfiel: java_vm_ext.cc:542] in call to SetByteField
F droid_boolfiel: java_vm_ext.cc:542] from void crc6463d68d2626be2acb.MainActivity.n_onCreate(android.os.Bundle)

Fix this by updating generator so that BoundFieldAsProperty.cs uses the parameter as-is when ISymbol.OnlyFormatOnMarshal=true.

The binding for RelativeLayout.LayoutParams.AlignWithParent becomes:

namespace Android.Widget;
public partial class RelativeLayout {
public new partial class LayoutParams {
[Register]
public bool AlignWithParent {
get => _members.InstanceFields.GetBooleanValue ("alignWithParent.Z", this);
set {
_members.InstanceFields.SetValue("alignWithParent.Z", this, value);
}
}
}
}

i.e. calling JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, bool).

Fixes: dotnet/android#10404
Context: 57f7bc8
Commit 57f7bc8 updated `generator` to "avoid non-blittable types"
in native callback methods, for which there were two non-blittables:
* System.Boolean, which should be marshaled as a System.SByte, and
* System.Char, which should be marshaled as a System.UInt16.
The problem is that this hit a codepath which was *not*
"for native callback methods": field bindings.
Consider [`android.widget.RelativeLayout.LayoutParams.alignWithParent`][0]:
package android.widget;
public /* partial */ class RelativeLayout {
public /* partial */ class LayoutParams {
public boolean alignWithParent;
}
}
which is bound as [`RelativeLayout.LayoutParams.AlignWithParent`][1]:
namespace Android.Widget;
public partial class RelativeLayout {
public new partial class LayoutParams {
[Register]
public bool AlignWithParent {
get => _members.InstanceFields.GetBooleanValue ("alignWithParent.Z", this);
set {
_members.InstanceFields.SetValue("alignWithParent.Z", this, value ? (sbyte)1 : (sbyte)0);
}
}
}
}
The problem is the property setter, which calls
`Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, sbyte)`.
Before 57f7bc8, it would instead call
`Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, bool)`,
but with 57f7bc8 there are now runtime crashes when boolean fields
are accessed, starting in .NET 10 Preview 2.
The following code fragment:
var p = new RelativeLayout.LayoutParams (1, 2) {
AlignWithParent = true,
};
crashes with:
F droid_boolfiel: java_vm_ext.cc:542] JNI DETECTED ERROR IN APPLICATION: attempt to access field boolean android.widget.RelativeLayout$LayoutParams.alignWithParent of type boolean with the wrong type byte: 0x709385d8
F droid_boolfiel: java_vm_ext.cc:542] in call to SetByteField
F droid_boolfiel: java_vm_ext.cc:542] from void crc6463d68d2626be2acb.MainActivity.n_onCreate(android.os.Bundle)
Fix this by updating `generator` so that `BoundFieldAsProperty.cs`
uses the parameter as-is when `ISymbol.OnlyFormatOnMarshal`=true.
The binding for `RelativeLayout.LayoutParams.AlignWithParent` becomes:
namespace Android.Widget;
public partial class RelativeLayout {
public new partial class LayoutParams {
[Register]
public bool AlignWithParent {
get => _members.InstanceFields.GetBooleanValue ("alignWithParent.Z", this);
set {
_members.InstanceFields.SetValue("alignWithParent.Z", this, value);
}
}
}
}
i.e. calling `JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, bool)`.
[0]: https://developer.android.com/reference/android/widget/RelativeLayout.LayoutParams#alignWithParent
[1]: https://learn.microsoft.com/en-us/dotnet/api/android.widget.relativelayout.layoutparams.alignwithparent?view=net-android-34.0

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull Request Overview

This PR fixes a runtime crash in .NET 10 Preview 2 where boolean field setters were calling the wrong JNI method due to an unintended side effect of commit 57f7bc8. The issue occurred when the generator's "avoid non-blittable types" logic, intended for native callback methods, was incorrectly applied to field bindings.

  • Fixes field property setters to use the correct parameter type instead of converting to native types
  • Restores proper boolean field handling by preserving the original parameter when OnlyFormatOnMarshal is true
  • Adds test coverage for boolean and char field bindings to prevent regression

Reviewed Changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
FileDescription
tools/generator/SourceWriters/BoundFieldAsProperty.csCore fix - conditionally preserve parameter type for field setters when OnlyFormatOnMarshal is true
tests/generator-Tests/expected.xaji/StaticFields/Xamarin.Test.SomeObject.csTest output showing corrected static boolean/char field property generation
tests/generator-Tests/expected.xaji/NonStaticFields/Xamarin.Test.SomeObject.csTest output showing corrected instance boolean/char field property generation
tests/generator-Tests/expected.ji/StaticFields/Xamarin.Test.SomeObject.csTest output for Java.Interop target showing corrected static field generation
tests/generator-Tests/expected.ji/StaticFields/StaticField.xmlTest metadata defining boolean and char fields for static field tests
tests/generator-Tests/expected.ji/NonStaticFields/Xamarin.Test.SomeObject.csTest output for Java.Interop target showing corrected instance field generation
tests/generator-Tests/expected.ji/NonStaticFields/NonStaticField.xmlTest metadata defining boolean and char fields for instance field tests

@jonathanpeppers
jonathanpeppers enabled auto-merge (squash) August 12, 2025 18:44
@jonathanpeppers
jonathanpeppers merged commit 90ac202 into dotnet:mainAug 12, 2025
2 checks passed
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Sep 12, 2025
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.

JNI DETECTED ERROR IN APPLICATION around accessing boolean fields

4 participants

@jonpryor@grendello@jonathanpeppers
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Aug 27, 2026. It is now read-only.

[generator] Don't avoid blittable types for fields - #1353

Merged
jonathanpeppers merged 2 commits into
dotnet:mainfrom
jonpryor:dev/jonpryor/jonp-field-SetValue-boolean
Aug 12, 2025
Merged

[generator] Don't avoid blittable types for fields#1353
jonathanpeppers merged 2 commits into
dotnet:mainfrom
jonpryor:dev/jonpryor/jonp-field-SetValue-boolean

Conversation

@jonpryor

Copy link
Copy Markdown
Contributor

Fixes: dotnet/android#10404

Context: 57f7bc8

Commit 57f7bc8 updated generator to "avoid non-blittable types" in native callback methods, for which there were two non-blittables:

  • System.Boolean, which should be marshaled as a System.SByte, and
  • System.Char, which should be marshaled as a System.UInt16.

The problem is that this hit a codepath which was not "for native callback methods": field bindings.

Consider android.widget.RelativeLayout.LayoutParams.alignWithParent:

package android.widget;
public /* partial */ class RelativeLayout {
public /* partial */ class LayoutParams {
public boolean alignWithParent;
}
}

which is bound as RelativeLayout.LayoutParams.AlignWithParent:

namespace Android.Widget;
public partial class RelativeLayout {
public new partial class LayoutParams {
[Register]
public bool AlignWithParent {
get => _members.InstanceFields.GetBooleanValue ("alignWithParent.Z", this);
set {
_members.InstanceFields.SetValue("alignWithParent.Z", this, value ? (sbyte)1 : (sbyte)0);
}
}
}
}

The problem is the property setter, which calls
Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, sbyte). Before 57f7bc8, it would instead call
Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, bool), but with 57f7bc8 there are now runtime crashes when boolean fields are accessed, starting in .NET 10 Preview 2.

The following code fragment:

var p = new RelativeLayout.LayoutParams (1, 2) {
AlignWithParent = true,
};

crashes with:

F droid_boolfiel: java_vm_ext.cc:542] JNI DETECTED ERROR IN APPLICATION: attempt to access field boolean android.widget.RelativeLayout$LayoutParams.alignWithParent of type boolean with the wrong type byte: 0x709385d8
F droid_boolfiel: java_vm_ext.cc:542] in call to SetByteField
F droid_boolfiel: java_vm_ext.cc:542] from void crc6463d68d2626be2acb.MainActivity.n_onCreate(android.os.Bundle)

Fix this by updating generator so that BoundFieldAsProperty.cs uses the parameter as-is when ISymbol.OnlyFormatOnMarshal=true.

The binding for RelativeLayout.LayoutParams.AlignWithParent becomes:

namespace Android.Widget;
public partial class RelativeLayout {
public new partial class LayoutParams {
[Register]
public bool AlignWithParent {
get => _members.InstanceFields.GetBooleanValue ("alignWithParent.Z", this);
set {
_members.InstanceFields.SetValue("alignWithParent.Z", this, value);
}
}
}
}

i.e. calling JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, bool).

Fixes: dotnet/android#10404
Context: 57f7bc8
Commit 57f7bc8 updated `generator` to "avoid non-blittable types"
in native callback methods, for which there were two non-blittables:
* System.Boolean, which should be marshaled as a System.SByte, and
* System.Char, which should be marshaled as a System.UInt16.
The problem is that this hit a codepath which was *not*
"for native callback methods": field bindings.
Consider [`android.widget.RelativeLayout.LayoutParams.alignWithParent`][0]:
package android.widget;
public /* partial */ class RelativeLayout {
public /* partial */ class LayoutParams {
public boolean alignWithParent;
}
}
which is bound as [`RelativeLayout.LayoutParams.AlignWithParent`][1]:
namespace Android.Widget;
public partial class RelativeLayout {
public new partial class LayoutParams {
[Register]
public bool AlignWithParent {
get => _members.InstanceFields.GetBooleanValue ("alignWithParent.Z", this);
set {
_members.InstanceFields.SetValue("alignWithParent.Z", this, value ? (sbyte)1 : (sbyte)0);
}
}
}
}
The problem is the property setter, which calls
`Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, sbyte)`.
Before 57f7bc8, it would instead call
`Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, bool)`,
but with 57f7bc8 there are now runtime crashes when boolean fields
are accessed, starting in .NET 10 Preview 2.
The following code fragment:
var p = new RelativeLayout.LayoutParams (1, 2) {
AlignWithParent = true,
};
crashes with:
F droid_boolfiel: java_vm_ext.cc:542] JNI DETECTED ERROR IN APPLICATION: attempt to access field boolean android.widget.RelativeLayout$LayoutParams.alignWithParent of type boolean with the wrong type byte: 0x709385d8
F droid_boolfiel: java_vm_ext.cc:542] in call to SetByteField
F droid_boolfiel: java_vm_ext.cc:542] from void crc6463d68d2626be2acb.MainActivity.n_onCreate(android.os.Bundle)
Fix this by updating `generator` so that `BoundFieldAsProperty.cs`
uses the parameter as-is when `ISymbol.OnlyFormatOnMarshal`=true.
The binding for `RelativeLayout.LayoutParams.AlignWithParent` becomes:
namespace Android.Widget;
public partial class RelativeLayout {
public new partial class LayoutParams {
[Register]
public bool AlignWithParent {
get => _members.InstanceFields.GetBooleanValue ("alignWithParent.Z", this);
set {
_members.InstanceFields.SetValue("alignWithParent.Z", this, value);
}
}
}
}
i.e. calling `JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, bool)`.
[0]: https://developer.android.com/reference/android/widget/RelativeLayout.LayoutParams#alignWithParent
[1]: https://learn.microsoft.com/en-us/dotnet/api/android.widget.relativelayout.layoutparams.alignwithparent?view=net-android-34.0

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull Request Overview

This PR fixes a runtime crash in .NET 10 Preview 2 where boolean field setters were calling the wrong JNI method due to an unintended side effect of commit 57f7bc8. The issue occurred when the generator's "avoid non-blittable types" logic, intended for native callback methods, was incorrectly applied to field bindings.

  • Fixes field property setters to use the correct parameter type instead of converting to native types
  • Restores proper boolean field handling by preserving the original parameter when OnlyFormatOnMarshal is true
  • Adds test coverage for boolean and char field bindings to prevent regression

Reviewed Changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
FileDescription
tools/generator/SourceWriters/BoundFieldAsProperty.csCore fix - conditionally preserve parameter type for field setters when OnlyFormatOnMarshal is true
tests/generator-Tests/expected.xaji/StaticFields/Xamarin.Test.SomeObject.csTest output showing corrected static boolean/char field property generation
tests/generator-Tests/expected.xaji/NonStaticFields/Xamarin.Test.SomeObject.csTest output showing corrected instance boolean/char field property generation
tests/generator-Tests/expected.ji/StaticFields/Xamarin.Test.SomeObject.csTest output for Java.Interop target showing corrected static field generation
tests/generator-Tests/expected.ji/StaticFields/StaticField.xmlTest metadata defining boolean and char fields for static field tests
tests/generator-Tests/expected.ji/NonStaticFields/Xamarin.Test.SomeObject.csTest output for Java.Interop target showing corrected instance field generation
tests/generator-Tests/expected.ji/NonStaticFields/NonStaticField.xmlTest metadata defining boolean and char fields for instance field tests

@jonathanpeppers
jonathanpeppers enabled auto-merge (squash) August 12, 2025 18:44
@jonathanpeppers
jonathanpeppers merged commit 90ac202 into dotnet:mainAug 12, 2025
2 checks passed
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Sep 12, 2025
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.

JNI DETECTED ERROR IN APPLICATION around accessing boolean fields

4 participants

@jonpryor@grendello@jonathanpeppers
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Aug 27, 2026. It is now read-only.

[generator] Don't avoid blittable types for fields - #1353

Merged
jonathanpeppers merged 2 commits into
dotnet:mainfrom
jonpryor:dev/jonpryor/jonp-field-SetValue-boolean
Aug 12, 2025
Merged

[generator] Don't avoid blittable types for fields#1353
jonathanpeppers merged 2 commits into
dotnet:mainfrom
jonpryor:dev/jonpryor/jonp-field-SetValue-boolean

Conversation

@jonpryor

Copy link
Copy Markdown
Contributor

Fixes: dotnet/android#10404

Context: 57f7bc8

Commit 57f7bc8 updated generator to "avoid non-blittable types" in native callback methods, for which there were two non-blittables:

  • System.Boolean, which should be marshaled as a System.SByte, and
  • System.Char, which should be marshaled as a System.UInt16.

The problem is that this hit a codepath which was not "for native callback methods": field bindings.

Consider android.widget.RelativeLayout.LayoutParams.alignWithParent:

package android.widget;
public /* partial */ class RelativeLayout {
public /* partial */ class LayoutParams {
public boolean alignWithParent;
}
}

which is bound as RelativeLayout.LayoutParams.AlignWithParent:

namespace Android.Widget;
public partial class RelativeLayout {
public new partial class LayoutParams {
[Register]
public bool AlignWithParent {
get => _members.InstanceFields.GetBooleanValue ("alignWithParent.Z", this);
set {
_members.InstanceFields.SetValue("alignWithParent.Z", this, value ? (sbyte)1 : (sbyte)0);
}
}
}
}

The problem is the property setter, which calls
Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, sbyte). Before 57f7bc8, it would instead call
Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, bool), but with 57f7bc8 there are now runtime crashes when boolean fields are accessed, starting in .NET 10 Preview 2.

The following code fragment:

var p = new RelativeLayout.LayoutParams (1, 2) {
AlignWithParent = true,
};

crashes with:

F droid_boolfiel: java_vm_ext.cc:542] JNI DETECTED ERROR IN APPLICATION: attempt to access field boolean android.widget.RelativeLayout$LayoutParams.alignWithParent of type boolean with the wrong type byte: 0x709385d8
F droid_boolfiel: java_vm_ext.cc:542] in call to SetByteField
F droid_boolfiel: java_vm_ext.cc:542] from void crc6463d68d2626be2acb.MainActivity.n_onCreate(android.os.Bundle)

Fix this by updating generator so that BoundFieldAsProperty.cs uses the parameter as-is when ISymbol.OnlyFormatOnMarshal=true.

The binding for RelativeLayout.LayoutParams.AlignWithParent becomes:

namespace Android.Widget;
public partial class RelativeLayout {
public new partial class LayoutParams {
[Register]
public bool AlignWithParent {
get => _members.InstanceFields.GetBooleanValue ("alignWithParent.Z", this);
set {
_members.InstanceFields.SetValue("alignWithParent.Z", this, value);
}
}
}
}

i.e. calling JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, bool).

Fixes: dotnet/android#10404
Context: 57f7bc8
Commit 57f7bc8 updated `generator` to "avoid non-blittable types"
in native callback methods, for which there were two non-blittables:
* System.Boolean, which should be marshaled as a System.SByte, and
* System.Char, which should be marshaled as a System.UInt16.
The problem is that this hit a codepath which was *not*
"for native callback methods": field bindings.
Consider [`android.widget.RelativeLayout.LayoutParams.alignWithParent`][0]:
package android.widget;
public /* partial */ class RelativeLayout {
public /* partial */ class LayoutParams {
public boolean alignWithParent;
}
}
which is bound as [`RelativeLayout.LayoutParams.AlignWithParent`][1]:
namespace Android.Widget;
public partial class RelativeLayout {
public new partial class LayoutParams {
[Register]
public bool AlignWithParent {
get => _members.InstanceFields.GetBooleanValue ("alignWithParent.Z", this);
set {
_members.InstanceFields.SetValue("alignWithParent.Z", this, value ? (sbyte)1 : (sbyte)0);
}
}
}
}
The problem is the property setter, which calls
`Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, sbyte)`.
Before 57f7bc8, it would instead call
`Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, bool)`,
but with 57f7bc8 there are now runtime crashes when boolean fields
are accessed, starting in .NET 10 Preview 2.
The following code fragment:
var p = new RelativeLayout.LayoutParams (1, 2) {
AlignWithParent = true,
};
crashes with:
F droid_boolfiel: java_vm_ext.cc:542] JNI DETECTED ERROR IN APPLICATION: attempt to access field boolean android.widget.RelativeLayout$LayoutParams.alignWithParent of type boolean with the wrong type byte: 0x709385d8
F droid_boolfiel: java_vm_ext.cc:542] in call to SetByteField
F droid_boolfiel: java_vm_ext.cc:542] from void crc6463d68d2626be2acb.MainActivity.n_onCreate(android.os.Bundle)
Fix this by updating `generator` so that `BoundFieldAsProperty.cs`
uses the parameter as-is when `ISymbol.OnlyFormatOnMarshal`=true.
The binding for `RelativeLayout.LayoutParams.AlignWithParent` becomes:
namespace Android.Widget;
public partial class RelativeLayout {
public new partial class LayoutParams {
[Register]
public bool AlignWithParent {
get => _members.InstanceFields.GetBooleanValue ("alignWithParent.Z", this);
set {
_members.InstanceFields.SetValue("alignWithParent.Z", this, value);
}
}
}
}
i.e. calling `JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, bool)`.
[0]: https://developer.android.com/reference/android/widget/RelativeLayout.LayoutParams#alignWithParent
[1]: https://learn.microsoft.com/en-us/dotnet/api/android.widget.relativelayout.layoutparams.alignwithparent?view=net-android-34.0

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull Request Overview

This PR fixes a runtime crash in .NET 10 Preview 2 where boolean field setters were calling the wrong JNI method due to an unintended side effect of commit 57f7bc8. The issue occurred when the generator's "avoid non-blittable types" logic, intended for native callback methods, was incorrectly applied to field bindings.

  • Fixes field property setters to use the correct parameter type instead of converting to native types
  • Restores proper boolean field handling by preserving the original parameter when OnlyFormatOnMarshal is true
  • Adds test coverage for boolean and char field bindings to prevent regression

Reviewed Changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
FileDescription
tools/generator/SourceWriters/BoundFieldAsProperty.csCore fix - conditionally preserve parameter type for field setters when OnlyFormatOnMarshal is true
tests/generator-Tests/expected.xaji/StaticFields/Xamarin.Test.SomeObject.csTest output showing corrected static boolean/char field property generation
tests/generator-Tests/expected.xaji/NonStaticFields/Xamarin.Test.SomeObject.csTest output showing corrected instance boolean/char field property generation
tests/generator-Tests/expected.ji/StaticFields/Xamarin.Test.SomeObject.csTest output for Java.Interop target showing corrected static field generation
tests/generator-Tests/expected.ji/StaticFields/StaticField.xmlTest metadata defining boolean and char fields for static field tests
tests/generator-Tests/expected.ji/NonStaticFields/Xamarin.Test.SomeObject.csTest output for Java.Interop target showing corrected instance field generation
tests/generator-Tests/expected.ji/NonStaticFields/NonStaticField.xmlTest metadata defining boolean and char fields for instance field tests

@jonathanpeppers
jonathanpeppers enabled auto-merge (squash) August 12, 2025 18:44
@jonathanpeppers
jonathanpeppers merged commit 90ac202 into dotnet:mainAug 12, 2025
2 checks passed
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Sep 12, 2025
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.

JNI DETECTED ERROR IN APPLICATION around accessing boolean fields

4 participants

@jonpryor@grendello@jonathanpeppers
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
This repository was archived by the owner on Aug 27, 2026. It is now read-only.

[generator] Don't avoid blittable types for fields - #1353

Merged
jonathanpeppers merged 2 commits into
dotnet:mainfrom
jonpryor:dev/jonpryor/jonp-field-SetValue-boolean
Aug 12, 2025
Merged

[generator] Don't avoid blittable types for fields#1353
jonathanpeppers merged 2 commits into
dotnet:mainfrom
jonpryor:dev/jonpryor/jonp-field-SetValue-boolean

Conversation

@jonpryor

Copy link
Copy Markdown
Contributor

Fixes: dotnet/android#10404

Context: 57f7bc8

Commit 57f7bc8 updated generator to "avoid non-blittable types" in native callback methods, for which there were two non-blittables:

  • System.Boolean, which should be marshaled as a System.SByte, and
  • System.Char, which should be marshaled as a System.UInt16.

The problem is that this hit a codepath which was not "for native callback methods": field bindings.

Consider android.widget.RelativeLayout.LayoutParams.alignWithParent:

package android.widget;
public /* partial */ class RelativeLayout {
public /* partial */ class LayoutParams {
public boolean alignWithParent;
}
}

which is bound as RelativeLayout.LayoutParams.AlignWithParent:

namespace Android.Widget;
public partial class RelativeLayout {
public new partial class LayoutParams {
[Register]
public bool AlignWithParent {
get => _members.InstanceFields.GetBooleanValue ("alignWithParent.Z", this);
set {
_members.InstanceFields.SetValue("alignWithParent.Z", this, value ? (sbyte)1 : (sbyte)0);
}
}
}
}

The problem is the property setter, which calls
Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, sbyte). Before 57f7bc8, it would instead call
Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, bool), but with 57f7bc8 there are now runtime crashes when boolean fields are accessed, starting in .NET 10 Preview 2.

The following code fragment:

var p = new RelativeLayout.LayoutParams (1, 2) {
AlignWithParent = true,
};

crashes with:

F droid_boolfiel: java_vm_ext.cc:542] JNI DETECTED ERROR IN APPLICATION: attempt to access field boolean android.widget.RelativeLayout$LayoutParams.alignWithParent of type boolean with the wrong type byte: 0x709385d8
F droid_boolfiel: java_vm_ext.cc:542] in call to SetByteField
F droid_boolfiel: java_vm_ext.cc:542] from void crc6463d68d2626be2acb.MainActivity.n_onCreate(android.os.Bundle)

Fix this by updating generator so that BoundFieldAsProperty.cs uses the parameter as-is when ISymbol.OnlyFormatOnMarshal=true.

The binding for RelativeLayout.LayoutParams.AlignWithParent becomes:

namespace Android.Widget;
public partial class RelativeLayout {
public new partial class LayoutParams {
[Register]
public bool AlignWithParent {
get => _members.InstanceFields.GetBooleanValue ("alignWithParent.Z", this);
set {
_members.InstanceFields.SetValue("alignWithParent.Z", this, value);
}
}
}
}

i.e. calling JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, bool).

Fixes: dotnet/android#10404
Context: 57f7bc8
Commit 57f7bc8 updated `generator` to "avoid non-blittable types"
in native callback methods, for which there were two non-blittables:
* System.Boolean, which should be marshaled as a System.SByte, and
* System.Char, which should be marshaled as a System.UInt16.
The problem is that this hit a codepath which was *not*
"for native callback methods": field bindings.
Consider [`android.widget.RelativeLayout.LayoutParams.alignWithParent`][0]:
package android.widget;
public /* partial */ class RelativeLayout {
public /* partial */ class LayoutParams {
public boolean alignWithParent;
}
}
which is bound as [`RelativeLayout.LayoutParams.AlignWithParent`][1]:
namespace Android.Widget;
public partial class RelativeLayout {
public new partial class LayoutParams {
[Register]
public bool AlignWithParent {
get => _members.InstanceFields.GetBooleanValue ("alignWithParent.Z", this);
set {
_members.InstanceFields.SetValue("alignWithParent.Z", this, value ? (sbyte)1 : (sbyte)0);
}
}
}
}
The problem is the property setter, which calls
`Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, sbyte)`.
Before 57f7bc8, it would instead call
`Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, bool)`,
but with 57f7bc8 there are now runtime crashes when boolean fields
are accessed, starting in .NET 10 Preview 2.
The following code fragment:
var p = new RelativeLayout.LayoutParams (1, 2) {
AlignWithParent = true,
};
crashes with:
F droid_boolfiel: java_vm_ext.cc:542] JNI DETECTED ERROR IN APPLICATION: attempt to access field boolean android.widget.RelativeLayout$LayoutParams.alignWithParent of type boolean with the wrong type byte: 0x709385d8
F droid_boolfiel: java_vm_ext.cc:542] in call to SetByteField
F droid_boolfiel: java_vm_ext.cc:542] from void crc6463d68d2626be2acb.MainActivity.n_onCreate(android.os.Bundle)
Fix this by updating `generator` so that `BoundFieldAsProperty.cs`
uses the parameter as-is when `ISymbol.OnlyFormatOnMarshal`=true.
The binding for `RelativeLayout.LayoutParams.AlignWithParent` becomes:
namespace Android.Widget;
public partial class RelativeLayout {
public new partial class LayoutParams {
[Register]
public bool AlignWithParent {
get => _members.InstanceFields.GetBooleanValue ("alignWithParent.Z", this);
set {
_members.InstanceFields.SetValue("alignWithParent.Z", this, value);
}
}
}
}
i.e. calling `JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, bool)`.
[0]: https://developer.android.com/reference/android/widget/RelativeLayout.LayoutParams#alignWithParent
[1]: https://learn.microsoft.com/en-us/dotnet/api/android.widget.relativelayout.layoutparams.alignwithparent?view=net-android-34.0

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull Request Overview

This PR fixes a runtime crash in .NET 10 Preview 2 where boolean field setters were calling the wrong JNI method due to an unintended side effect of commit 57f7bc8. The issue occurred when the generator's "avoid non-blittable types" logic, intended for native callback methods, was incorrectly applied to field bindings.

  • Fixes field property setters to use the correct parameter type instead of converting to native types
  • Restores proper boolean field handling by preserving the original parameter when OnlyFormatOnMarshal is true
  • Adds test coverage for boolean and char field bindings to prevent regression

Reviewed Changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
FileDescription
tools/generator/SourceWriters/BoundFieldAsProperty.csCore fix - conditionally preserve parameter type for field setters when OnlyFormatOnMarshal is true
tests/generator-Tests/expected.xaji/StaticFields/Xamarin.Test.SomeObject.csTest output showing corrected static boolean/char field property generation
tests/generator-Tests/expected.xaji/NonStaticFields/Xamarin.Test.SomeObject.csTest output showing corrected instance boolean/char field property generation
tests/generator-Tests/expected.ji/StaticFields/Xamarin.Test.SomeObject.csTest output for Java.Interop target showing corrected static field generation
tests/generator-Tests/expected.ji/StaticFields/StaticField.xmlTest metadata defining boolean and char fields for static field tests
tests/generator-Tests/expected.ji/NonStaticFields/Xamarin.Test.SomeObject.csTest output for Java.Interop target showing corrected instance field generation
tests/generator-Tests/expected.ji/NonStaticFields/NonStaticField.xmlTest metadata defining boolean and char fields for instance field tests

@jonathanpeppers
jonathanpeppers enabled auto-merge (squash) August 12, 2025 18:44
@jonathanpeppers
jonathanpeppers merged commit 90ac202 into dotnet:mainAug 12, 2025
2 checks passed
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Sep 12, 2025
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.

JNI DETECTED ERROR IN APPLICATION around accessing boolean fields

4 participants

@jonpryor@grendello@jonathanpeppers
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Aug 27, 2026. It is now read-only.

[generator] Don't avoid blittable types for fields - #1353

Merged
jonathanpeppers merged 2 commits into
dotnet:mainfrom
jonpryor:dev/jonpryor/jonp-field-SetValue-boolean
Aug 12, 2025
Merged

[generator] Don't avoid blittable types for fields#1353
jonathanpeppers merged 2 commits into
dotnet:mainfrom
jonpryor:dev/jonpryor/jonp-field-SetValue-boolean

Conversation

@jonpryor

Copy link
Copy Markdown
Contributor

Fixes: dotnet/android#10404

Context: 57f7bc8

Commit 57f7bc8 updated generator to "avoid non-blittable types" in native callback methods, for which there were two non-blittables:

  • System.Boolean, which should be marshaled as a System.SByte, and
  • System.Char, which should be marshaled as a System.UInt16.

The problem is that this hit a codepath which was not "for native callback methods": field bindings.

Consider android.widget.RelativeLayout.LayoutParams.alignWithParent:

package android.widget;
public /* partial */ class RelativeLayout {
public /* partial */ class LayoutParams {
public boolean alignWithParent;
}
}

which is bound as RelativeLayout.LayoutParams.AlignWithParent:

namespace Android.Widget;
public partial class RelativeLayout {
public new partial class LayoutParams {
[Register]
public bool AlignWithParent {
get => _members.InstanceFields.GetBooleanValue ("alignWithParent.Z", this);
set {
_members.InstanceFields.SetValue("alignWithParent.Z", this, value ? (sbyte)1 : (sbyte)0);
}
}
}
}

The problem is the property setter, which calls
Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, sbyte). Before 57f7bc8, it would instead call
Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, bool), but with 57f7bc8 there are now runtime crashes when boolean fields are accessed, starting in .NET 10 Preview 2.

The following code fragment:

var p = new RelativeLayout.LayoutParams (1, 2) {
AlignWithParent = true,
};

crashes with:

F droid_boolfiel: java_vm_ext.cc:542] JNI DETECTED ERROR IN APPLICATION: attempt to access field boolean android.widget.RelativeLayout$LayoutParams.alignWithParent of type boolean with the wrong type byte: 0x709385d8
F droid_boolfiel: java_vm_ext.cc:542] in call to SetByteField
F droid_boolfiel: java_vm_ext.cc:542] from void crc6463d68d2626be2acb.MainActivity.n_onCreate(android.os.Bundle)

Fix this by updating generator so that BoundFieldAsProperty.cs uses the parameter as-is when ISymbol.OnlyFormatOnMarshal=true.

The binding for RelativeLayout.LayoutParams.AlignWithParent becomes:

namespace Android.Widget;
public partial class RelativeLayout {
public new partial class LayoutParams {
[Register]
public bool AlignWithParent {
get => _members.InstanceFields.GetBooleanValue ("alignWithParent.Z", this);
set {
_members.InstanceFields.SetValue("alignWithParent.Z", this, value);
}
}
}
}

i.e. calling JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, bool).

Fixes: dotnet/android#10404
Context: 57f7bc8
Commit 57f7bc8 updated `generator` to "avoid non-blittable types"
in native callback methods, for which there were two non-blittables:
* System.Boolean, which should be marshaled as a System.SByte, and
* System.Char, which should be marshaled as a System.UInt16.
The problem is that this hit a codepath which was *not*
"for native callback methods": field bindings.
Consider [`android.widget.RelativeLayout.LayoutParams.alignWithParent`][0]:
package android.widget;
public /* partial */ class RelativeLayout {
public /* partial */ class LayoutParams {
public boolean alignWithParent;
}
}
which is bound as [`RelativeLayout.LayoutParams.AlignWithParent`][1]:
namespace Android.Widget;
public partial class RelativeLayout {
public new partial class LayoutParams {
[Register]
public bool AlignWithParent {
get => _members.InstanceFields.GetBooleanValue ("alignWithParent.Z", this);
set {
_members.InstanceFields.SetValue("alignWithParent.Z", this, value ? (sbyte)1 : (sbyte)0);
}
}
}
}
The problem is the property setter, which calls
`Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, sbyte)`.
Before 57f7bc8, it would instead call
`Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, bool)`,
but with 57f7bc8 there are now runtime crashes when boolean fields
are accessed, starting in .NET 10 Preview 2.
The following code fragment:
var p = new RelativeLayout.LayoutParams (1, 2) {
AlignWithParent = true,
};
crashes with:
F droid_boolfiel: java_vm_ext.cc:542] JNI DETECTED ERROR IN APPLICATION: attempt to access field boolean android.widget.RelativeLayout$LayoutParams.alignWithParent of type boolean with the wrong type byte: 0x709385d8
F droid_boolfiel: java_vm_ext.cc:542] in call to SetByteField
F droid_boolfiel: java_vm_ext.cc:542] from void crc6463d68d2626be2acb.MainActivity.n_onCreate(android.os.Bundle)
Fix this by updating `generator` so that `BoundFieldAsProperty.cs`
uses the parameter as-is when `ISymbol.OnlyFormatOnMarshal`=true.
The binding for `RelativeLayout.LayoutParams.AlignWithParent` becomes:
namespace Android.Widget;
public partial class RelativeLayout {
public new partial class LayoutParams {
[Register]
public bool AlignWithParent {
get => _members.InstanceFields.GetBooleanValue ("alignWithParent.Z", this);
set {
_members.InstanceFields.SetValue("alignWithParent.Z", this, value);
}
}
}
}
i.e. calling `JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, bool)`.
[0]: https://developer.android.com/reference/android/widget/RelativeLayout.LayoutParams#alignWithParent
[1]: https://learn.microsoft.com/en-us/dotnet/api/android.widget.relativelayout.layoutparams.alignwithparent?view=net-android-34.0

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull Request Overview

This PR fixes a runtime crash in .NET 10 Preview 2 where boolean field setters were calling the wrong JNI method due to an unintended side effect of commit 57f7bc8. The issue occurred when the generator's "avoid non-blittable types" logic, intended for native callback methods, was incorrectly applied to field bindings.

  • Fixes field property setters to use the correct parameter type instead of converting to native types
  • Restores proper boolean field handling by preserving the original parameter when OnlyFormatOnMarshal is true
  • Adds test coverage for boolean and char field bindings to prevent regression

Reviewed Changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
FileDescription
tools/generator/SourceWriters/BoundFieldAsProperty.csCore fix - conditionally preserve parameter type for field setters when OnlyFormatOnMarshal is true
tests/generator-Tests/expected.xaji/StaticFields/Xamarin.Test.SomeObject.csTest output showing corrected static boolean/char field property generation
tests/generator-Tests/expected.xaji/NonStaticFields/Xamarin.Test.SomeObject.csTest output showing corrected instance boolean/char field property generation
tests/generator-Tests/expected.ji/StaticFields/Xamarin.Test.SomeObject.csTest output for Java.Interop target showing corrected static field generation
tests/generator-Tests/expected.ji/StaticFields/StaticField.xmlTest metadata defining boolean and char fields for static field tests
tests/generator-Tests/expected.ji/NonStaticFields/Xamarin.Test.SomeObject.csTest output for Java.Interop target showing corrected instance field generation
tests/generator-Tests/expected.ji/NonStaticFields/NonStaticField.xmlTest metadata defining boolean and char fields for instance field tests

@jonathanpeppers
jonathanpeppers enabled auto-merge (squash) August 12, 2025 18:44
@jonathanpeppers
jonathanpeppers merged commit 90ac202 into dotnet:mainAug 12, 2025
2 checks passed
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Sep 12, 2025
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.

JNI DETECTED ERROR IN APPLICATION around accessing boolean fields

4 participants

@jonpryor@grendello@jonathanpeppers
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Aug 27, 2026. It is now read-only.

[generator] Don't avoid blittable types for fields - #1353

Merged
jonathanpeppers merged 2 commits into
dotnet:mainfrom
jonpryor:dev/jonpryor/jonp-field-SetValue-boolean
Aug 12, 2025
Merged

[generator] Don't avoid blittable types for fields#1353
jonathanpeppers merged 2 commits into
dotnet:mainfrom
jonpryor:dev/jonpryor/jonp-field-SetValue-boolean

Conversation

@jonpryor

Copy link
Copy Markdown
Contributor

Fixes: dotnet/android#10404

Context: 57f7bc8

Commit 57f7bc8 updated generator to "avoid non-blittable types" in native callback methods, for which there were two non-blittables:

  • System.Boolean, which should be marshaled as a System.SByte, and
  • System.Char, which should be marshaled as a System.UInt16.

The problem is that this hit a codepath which was not "for native callback methods": field bindings.

Consider android.widget.RelativeLayout.LayoutParams.alignWithParent:

package android.widget;
public /* partial */ class RelativeLayout {
public /* partial */ class LayoutParams {
public boolean alignWithParent;
}
}

which is bound as RelativeLayout.LayoutParams.AlignWithParent:

namespace Android.Widget;
public partial class RelativeLayout {
public new partial class LayoutParams {
[Register]
public bool AlignWithParent {
get => _members.InstanceFields.GetBooleanValue ("alignWithParent.Z", this);
set {
_members.InstanceFields.SetValue("alignWithParent.Z", this, value ? (sbyte)1 : (sbyte)0);
}
}
}
}

The problem is the property setter, which calls
Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, sbyte). Before 57f7bc8, it would instead call
Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, bool), but with 57f7bc8 there are now runtime crashes when boolean fields are accessed, starting in .NET 10 Preview 2.

The following code fragment:

var p = new RelativeLayout.LayoutParams (1, 2) {
AlignWithParent = true,
};

crashes with:

F droid_boolfiel: java_vm_ext.cc:542] JNI DETECTED ERROR IN APPLICATION: attempt to access field boolean android.widget.RelativeLayout$LayoutParams.alignWithParent of type boolean with the wrong type byte: 0x709385d8
F droid_boolfiel: java_vm_ext.cc:542] in call to SetByteField
F droid_boolfiel: java_vm_ext.cc:542] from void crc6463d68d2626be2acb.MainActivity.n_onCreate(android.os.Bundle)

Fix this by updating generator so that BoundFieldAsProperty.cs uses the parameter as-is when ISymbol.OnlyFormatOnMarshal=true.

The binding for RelativeLayout.LayoutParams.AlignWithParent becomes:

namespace Android.Widget;
public partial class RelativeLayout {
public new partial class LayoutParams {
[Register]
public bool AlignWithParent {
get => _members.InstanceFields.GetBooleanValue ("alignWithParent.Z", this);
set {
_members.InstanceFields.SetValue("alignWithParent.Z", this, value);
}
}
}
}

i.e. calling JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, bool).

Fixes: dotnet/android#10404
Context: 57f7bc8
Commit 57f7bc8 updated `generator` to "avoid non-blittable types"
in native callback methods, for which there were two non-blittables:
* System.Boolean, which should be marshaled as a System.SByte, and
* System.Char, which should be marshaled as a System.UInt16.
The problem is that this hit a codepath which was *not*
"for native callback methods": field bindings.
Consider [`android.widget.RelativeLayout.LayoutParams.alignWithParent`][0]:
package android.widget;
public /* partial */ class RelativeLayout {
public /* partial */ class LayoutParams {
public boolean alignWithParent;
}
}
which is bound as [`RelativeLayout.LayoutParams.AlignWithParent`][1]:
namespace Android.Widget;
public partial class RelativeLayout {
public new partial class LayoutParams {
[Register]
public bool AlignWithParent {
get => _members.InstanceFields.GetBooleanValue ("alignWithParent.Z", this);
set {
_members.InstanceFields.SetValue("alignWithParent.Z", this, value ? (sbyte)1 : (sbyte)0);
}
}
}
}
The problem is the property setter, which calls
`Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, sbyte)`.
Before 57f7bc8, it would instead call
`Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, bool)`,
but with 57f7bc8 there are now runtime crashes when boolean fields
are accessed, starting in .NET 10 Preview 2.
The following code fragment:
var p = new RelativeLayout.LayoutParams (1, 2) {
AlignWithParent = true,
};
crashes with:
F droid_boolfiel: java_vm_ext.cc:542] JNI DETECTED ERROR IN APPLICATION: attempt to access field boolean android.widget.RelativeLayout$LayoutParams.alignWithParent of type boolean with the wrong type byte: 0x709385d8
F droid_boolfiel: java_vm_ext.cc:542] in call to SetByteField
F droid_boolfiel: java_vm_ext.cc:542] from void crc6463d68d2626be2acb.MainActivity.n_onCreate(android.os.Bundle)
Fix this by updating `generator` so that `BoundFieldAsProperty.cs`
uses the parameter as-is when `ISymbol.OnlyFormatOnMarshal`=true.
The binding for `RelativeLayout.LayoutParams.AlignWithParent` becomes:
namespace Android.Widget;
public partial class RelativeLayout {
public new partial class LayoutParams {
[Register]
public bool AlignWithParent {
get => _members.InstanceFields.GetBooleanValue ("alignWithParent.Z", this);
set {
_members.InstanceFields.SetValue("alignWithParent.Z", this, value);
}
}
}
}
i.e. calling `JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, bool)`.
[0]: https://developer.android.com/reference/android/widget/RelativeLayout.LayoutParams#alignWithParent
[1]: https://learn.microsoft.com/en-us/dotnet/api/android.widget.relativelayout.layoutparams.alignwithparent?view=net-android-34.0

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull Request Overview

This PR fixes a runtime crash in .NET 10 Preview 2 where boolean field setters were calling the wrong JNI method due to an unintended side effect of commit 57f7bc8. The issue occurred when the generator's "avoid non-blittable types" logic, intended for native callback methods, was incorrectly applied to field bindings.

  • Fixes field property setters to use the correct parameter type instead of converting to native types
  • Restores proper boolean field handling by preserving the original parameter when OnlyFormatOnMarshal is true
  • Adds test coverage for boolean and char field bindings to prevent regression

Reviewed Changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
FileDescription
tools/generator/SourceWriters/BoundFieldAsProperty.csCore fix - conditionally preserve parameter type for field setters when OnlyFormatOnMarshal is true
tests/generator-Tests/expected.xaji/StaticFields/Xamarin.Test.SomeObject.csTest output showing corrected static boolean/char field property generation
tests/generator-Tests/expected.xaji/NonStaticFields/Xamarin.Test.SomeObject.csTest output showing corrected instance boolean/char field property generation
tests/generator-Tests/expected.ji/StaticFields/Xamarin.Test.SomeObject.csTest output for Java.Interop target showing corrected static field generation
tests/generator-Tests/expected.ji/StaticFields/StaticField.xmlTest metadata defining boolean and char fields for static field tests
tests/generator-Tests/expected.ji/NonStaticFields/Xamarin.Test.SomeObject.csTest output for Java.Interop target showing corrected instance field generation
tests/generator-Tests/expected.ji/NonStaticFields/NonStaticField.xmlTest metadata defining boolean and char fields for instance field tests

@jonathanpeppers
jonathanpeppers enabled auto-merge (squash) August 12, 2025 18:44
@jonathanpeppers
jonathanpeppers merged commit 90ac202 into dotnet:mainAug 12, 2025
2 checks passed
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Sep 12, 2025
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.

JNI DETECTED ERROR IN APPLICATION around accessing boolean fields

4 participants

@jonpryor@grendello@jonathanpeppers
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
This repository was archived by the owner on Aug 27, 2026. It is now read-only.

[generator] Don't avoid blittable types for fields - #1353

Merged
jonathanpeppers merged 2 commits into
dotnet:mainfrom
jonpryor:dev/jonpryor/jonp-field-SetValue-boolean
Aug 12, 2025
Merged

[generator] Don't avoid blittable types for fields#1353
jonathanpeppers merged 2 commits into
dotnet:mainfrom
jonpryor:dev/jonpryor/jonp-field-SetValue-boolean

Conversation

@jonpryor

Copy link
Copy Markdown
Contributor

Fixes: dotnet/android#10404

Context: 57f7bc8

Commit 57f7bc8 updated generator to "avoid non-blittable types" in native callback methods, for which there were two non-blittables:

  • System.Boolean, which should be marshaled as a System.SByte, and
  • System.Char, which should be marshaled as a System.UInt16.

The problem is that this hit a codepath which was not "for native callback methods": field bindings.

Consider android.widget.RelativeLayout.LayoutParams.alignWithParent:

package android.widget;
public /* partial */ class RelativeLayout {
public /* partial */ class LayoutParams {
public boolean alignWithParent;
}
}

which is bound as RelativeLayout.LayoutParams.AlignWithParent:

namespace Android.Widget;
public partial class RelativeLayout {
public new partial class LayoutParams {
[Register]
public bool AlignWithParent {
get => _members.InstanceFields.GetBooleanValue ("alignWithParent.Z", this);
set {
_members.InstanceFields.SetValue("alignWithParent.Z", this, value ? (sbyte)1 : (sbyte)0);
}
}
}
}

The problem is the property setter, which calls
Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, sbyte). Before 57f7bc8, it would instead call
Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, bool), but with 57f7bc8 there are now runtime crashes when boolean fields are accessed, starting in .NET 10 Preview 2.

The following code fragment:

var p = new RelativeLayout.LayoutParams (1, 2) {
AlignWithParent = true,
};

crashes with:

F droid_boolfiel: java_vm_ext.cc:542] JNI DETECTED ERROR IN APPLICATION: attempt to access field boolean android.widget.RelativeLayout$LayoutParams.alignWithParent of type boolean with the wrong type byte: 0x709385d8
F droid_boolfiel: java_vm_ext.cc:542] in call to SetByteField
F droid_boolfiel: java_vm_ext.cc:542] from void crc6463d68d2626be2acb.MainActivity.n_onCreate(android.os.Bundle)

Fix this by updating generator so that BoundFieldAsProperty.cs uses the parameter as-is when ISymbol.OnlyFormatOnMarshal=true.

The binding for RelativeLayout.LayoutParams.AlignWithParent becomes:

namespace Android.Widget;
public partial class RelativeLayout {
public new partial class LayoutParams {
[Register]
public bool AlignWithParent {
get => _members.InstanceFields.GetBooleanValue ("alignWithParent.Z", this);
set {
_members.InstanceFields.SetValue("alignWithParent.Z", this, value);
}
}
}
}

i.e. calling JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, bool).

Fixes: dotnet/android#10404
Context: 57f7bc8
Commit 57f7bc8 updated `generator` to "avoid non-blittable types"
in native callback methods, for which there were two non-blittables:
* System.Boolean, which should be marshaled as a System.SByte, and
* System.Char, which should be marshaled as a System.UInt16.
The problem is that this hit a codepath which was *not*
"for native callback methods": field bindings.
Consider [`android.widget.RelativeLayout.LayoutParams.alignWithParent`][0]:
package android.widget;
public /* partial */ class RelativeLayout {
public /* partial */ class LayoutParams {
public boolean alignWithParent;
}
}
which is bound as [`RelativeLayout.LayoutParams.AlignWithParent`][1]:
namespace Android.Widget;
public partial class RelativeLayout {
public new partial class LayoutParams {
[Register]
public bool AlignWithParent {
get => _members.InstanceFields.GetBooleanValue ("alignWithParent.Z", this);
set {
_members.InstanceFields.SetValue("alignWithParent.Z", this, value ? (sbyte)1 : (sbyte)0);
}
}
}
}
The problem is the property setter, which calls
`Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, sbyte)`.
Before 57f7bc8, it would instead call
`Java.Interop.JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, bool)`,
but with 57f7bc8 there are now runtime crashes when boolean fields
are accessed, starting in .NET 10 Preview 2.
The following code fragment:
var p = new RelativeLayout.LayoutParams (1, 2) {
AlignWithParent = true,
};
crashes with:
F droid_boolfiel: java_vm_ext.cc:542] JNI DETECTED ERROR IN APPLICATION: attempt to access field boolean android.widget.RelativeLayout$LayoutParams.alignWithParent of type boolean with the wrong type byte: 0x709385d8
F droid_boolfiel: java_vm_ext.cc:542] in call to SetByteField
F droid_boolfiel: java_vm_ext.cc:542] from void crc6463d68d2626be2acb.MainActivity.n_onCreate(android.os.Bundle)
Fix this by updating `generator` so that `BoundFieldAsProperty.cs`
uses the parameter as-is when `ISymbol.OnlyFormatOnMarshal`=true.
The binding for `RelativeLayout.LayoutParams.AlignWithParent` becomes:
namespace Android.Widget;
public partial class RelativeLayout {
public new partial class LayoutParams {
[Register]
public bool AlignWithParent {
get => _members.InstanceFields.GetBooleanValue ("alignWithParent.Z", this);
set {
_members.InstanceFields.SetValue("alignWithParent.Z", this, value);
}
}
}
}
i.e. calling `JniPeerMembers.JniInstanceFields.SetValue(string, IJavaPeerable, bool)`.
[0]: https://developer.android.com/reference/android/widget/RelativeLayout.LayoutParams#alignWithParent
[1]: https://learn.microsoft.com/en-us/dotnet/api/android.widget.relativelayout.layoutparams.alignwithparent?view=net-android-34.0

CopilotAI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull Request Overview

This PR fixes a runtime crash in .NET 10 Preview 2 where boolean field setters were calling the wrong JNI method due to an unintended side effect of commit 57f7bc8. The issue occurred when the generator's "avoid non-blittable types" logic, intended for native callback methods, was incorrectly applied to field bindings.

  • Fixes field property setters to use the correct parameter type instead of converting to native types
  • Restores proper boolean field handling by preserving the original parameter when OnlyFormatOnMarshal is true
  • Adds test coverage for boolean and char field bindings to prevent regression

Reviewed Changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
FileDescription
tools/generator/SourceWriters/BoundFieldAsProperty.csCore fix - conditionally preserve parameter type for field setters when OnlyFormatOnMarshal is true
tests/generator-Tests/expected.xaji/StaticFields/Xamarin.Test.SomeObject.csTest output showing corrected static boolean/char field property generation
tests/generator-Tests/expected.xaji/NonStaticFields/Xamarin.Test.SomeObject.csTest output showing corrected instance boolean/char field property generation
tests/generator-Tests/expected.ji/StaticFields/Xamarin.Test.SomeObject.csTest output for Java.Interop target showing corrected static field generation
tests/generator-Tests/expected.ji/StaticFields/StaticField.xmlTest metadata defining boolean and char fields for static field tests
tests/generator-Tests/expected.ji/NonStaticFields/Xamarin.Test.SomeObject.csTest output for Java.Interop target showing corrected instance field generation
tests/generator-Tests/expected.ji/NonStaticFields/NonStaticField.xmlTest metadata defining boolean and char fields for instance field tests

@jonathanpeppers
jonathanpeppers enabled auto-merge (squash) August 12, 2025 18:44
@jonathanpeppers
jonathanpeppers merged commit 90ac202 into dotnet:mainAug 12, 2025
2 checks passed
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Sep 12, 2025
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.

JNI DETECTED ERROR IN APPLICATION around accessing boolean fields

4 participants

@jonpryor@grendello@jonathanpeppers