[R8] [Optimization] Public fields in bindings are not protected by proguard rules
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 初心者へのやさしさ
- 22/100
- issue の種類
- バグ
- 明瞭さ
- おおむね明確
- 活発さ
- 活発
- 領域
- build-system, mobile
調査の方向性
Start with the generated proguard_project_references.cfg and compare its keep rules for com.facebook.LoggingBehavior and androidx.media3.exoplayer.ExoPlaybackException with the workaround rules in the issue. Then reproduce with TrimMode=full and AndroidLinkTool=r8 and check the R8 usage and proguard.map output for the removed enum value and the int to byte field change. Done means public fields and enum members used by bindings are kept, and the Type getter still matches the DEX field type.
索引モデルが issue の本文から書いたものです。
説明
Android framework version
net11.0-android (Preview)
Affected platform version
.NET 11.0.100-rc2
Description
It seems like public/protected fields in Java classes and enums, which managed code is accessing via bingings, are not protected by the generated proguard rules. This issue seems to be related to the optimization from https://github.com/dotnet/android/issues/12270, although most likely not caused by it.
Here are details that we discovered in our project, which is using native Facebook SDK binding and Xamarin.AndroidX.Media3.ExoPlayer nuget. During the build the following rules are generated in proguard_project_references.cfg:
-keep class com.facebook.LoggingBehavior
-keepclassmembers class com.facebook.LoggingBehavior {
}
-keep class androidx.media3.exoplayer.ExoPlaybackException
-keepclassmembers class androidx.media3.exoplayer.ExoPlaybackException {
}
com.facebook.LoggingBehavior is actually an enum, which values we are using via bindings, specifically
FacebookSdk.AddLoggingBehavior(LoggingBehavior.AppEvents);
FacebookSdk.AddLoggingBehavior(LoggingBehavior.Cache);
FacebookSdk.AddLoggingBehavior(LoggingBehavior.DeveloperErrors);
FacebookSdk.AddLoggingBehavior(LoggingBehavior.GraphApiDebugInfo);
FacebookSdk.AddLoggingBehavior(LoggingBehavior.GraphApiDebugWarning);
FacebookSdk.AddLoggingBehavior(LoggingBehavior.IncludeAccessTokens);
FacebookSdk.AddLoggingBehavior(LoggingBehavior.IncludeRawResponses);
FacebookSdk.AddLoggingBehavior(LoggingBehavior.Requests);
But because none of the enum values are protected by the generated rules, and with optimization enabled R8 decided to remove one of the values (seems like the only value with no explicit internal usage in Facebook SDK, at least after trimming). In the R8 "print usage" output there's the following record:
com.facebook.LoggingBehavior:
public static final enum com.facebook.LoggingBehavior CACHE
The case with androidx.media3.exoplayer.ExoPlaybackException is a bit different. We are using it's public Type field of type int like that:
if (exception is ExoPlaybackException error)
{
switch (error.Type)
{
...
}
}
In this case R8 does not remove the field completely, but performs another type of optimization (extracted from the proguard.map):
androidx.media3.exoplayer.ExoPlaybackException -> androidx.media3.exoplayer.ExoPlaybackException:
# {"id":"sourceFile","fileName":"ExoPlaybackException.java"}
boolean isRecoverable -> g
int type -> type
# {"id":"com.android.tools.r8.residualsignature","signature":"B"}
So the type of the field was optimized to be byte instead of int in DEX, while the binding code is still expecting int:
public int Type {
get {
return _members.InstanceFields.GetInt32Value ("type.I", this);
}
}
The issue probably become noticeable only after enabling R8 optimizations. We double-checked that with older .NET 10.0.200 same public fields are also not protected by default:
-keep class com.facebook.LoggingBehavior
-keepclassmembers class com.facebook.LoggingBehavior {
*** valueOf(...);
*** values(...);
}
-keep class androidx.media3.exoplayer.ExoPlaybackException
-keepclassmembers class androidx.media3.exoplayer.ExoPlaybackException {
*** getRendererException(...);
*** getSourceException(...);
*** getUnexpectedException(...);
*** createForRemote(...);
*** createForRenderer(...);
*** createForRenderer(...);
*** createForSource(...);
*** createForUnexpected(...);
*** createForUnexpected(...);
}
Steps to Reproduce
Seems like the issue can be reproduced on any .NET and Android workload version, but may lead to runtime crashes only in setup with R8 optimization enabled (11.0.100-rc.2/10.0.402)
- Android project with
TrimMode=fullandAndroidLinkTool=r8 - Access any native public field (like enum value) via binding
- Build project and check generated
proguard_project_references.cfg
Did you find any workaround?
Custom proguard rules file to protect public fields and enums:
-keepclassmembers enum * {
*;
}
-keepclassmembers class * {
public protected !static <fields>;
public protected static !final <fields>;
public protected static final ** *;
public protected static final **[] *;
}
Relevant log output
- 主要言語
- C#
- スター
- 2.1k
- フォーク
- 581
- 平均マージ
- 1日 15時間
- マージ済み PR(30日)
- 228
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートあり
- コントリビューションガイドなし
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
dotnet/android のほかの issue
-
Area: App+Library Build
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
メンテナーはふだん 1 日以内に返信
-
Area: Mono.Android
難易度 2/5 1〜3時間 初心者へのやさしさ 65/100
dotnet/android#9192 · コメント 4 件 · リアクション 1 件 ·
メンテナーはふだん 1 日以内に返信
-
Area: App+Library Build needs-triage
難易度 3/5 1〜2日 初心者へのやさしさ 66/100
メンテナーはふだん 1 日以内に返信
-
Area: Mono.Android needs-triage
難易度 4/5 3〜5日 初心者へのやさしさ 30/100
メンテナーはふだん 1 日以内に返信
-
Area: App Runtime needs-triage
難易度 4/5 3〜5日 初心者へのやさしさ 22/100
メンテナーはふだん 1 日以内に返信
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 66/100
qew21/Genshin-Subtitles#45 ·
-
bug priority: P2
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 66/100
space-wizards/RobustToolbox#7158 ·
メンテナーはふだん 1 日以内に返信
-
:watch: Not Triaged dotnet-csharp/svc fundamentals/subsvc
難易度 1/5 1時間未満 初心者へのやさしさ 88/100
メンテナーはふだん 1 日以内に返信
-
Wrong values of Kernel32.FileShare.Delete and Kernel32.FileAttributes.PosixSemantics対応中かも @ElectLive が今日担当しました。 オープンbug good first issue help wanted
難易度 1/5 1時間未満 初心者へのやさしさ 83/100
ForNeVeR/TruePath#241 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信