Status Update
Comments
uc...@google.com <uc...@google.com> #2
* GC ROOT android.support.v4.media.session.MediaSessionCompat$MediaSessionImplApi21$ExtraSession.this$0
* references android.support.v4.media.session.MediaSessionCompat$MediaSessionImplApi21.mSessionObj
* references android.media.session.MediaSession.mController
* references android.media.session.MediaController.mContext
* leaks com.bubenheimer.rucksack.d.q instance
je...@google.com <je...@google.com>
ga...@google.com <ga...@google.com> #3
ga...@google.com <ga...@google.com> #4
ha...@googlemail.com <ha...@googlemail.com> #5
Can you please confirm whether this is still reproducible on API 33?
And if you happen to have access, also on the Developer Preview of API 34?
ha...@googlemail.com <ha...@googlemail.com> #6
ha...@googlemail.com <ha...@googlemail.com> #7
Final thing, is this a dup of
je...@google.com <je...@google.com>
ga...@google.com <ga...@google.com> #8
Thanks, I believe it's a dup at this point.
The other issue was marked as fixed a year ago, but is still as reproducible as ever, I had just tested it on API 33 and UpsideDownCake DP2.
ma...@gmail.com <ma...@gmail.com> #9
I suppose I cannot say for sure that the two issues have the same root cause, there may be more than one cause for MediaBrowserService(Compat) leaks.
I just tested this issue here once more on my production app, on API 33 (emulator), and got a leak trace (with current LeakCanary) that closely resembles the original one I posted years ago. I let the app sit idle for another half hour, occasionally forcing a garbage collection via Android Studio Profiler, but my destroyed MediaBrowserServiceCompat (CW) instance just would not release. (I validated non-release by logging from finalize()
method, which looks very reliable.)
====================================
HEAP ANALYSIS RESULT
====================================
1 APPLICATION LEAKS
References underlined with "~~~" are likely causes.
Learn more at https://squ.re/leaks.
Signature: 881c4404fc048402f456764f134ed07390863849
┬───
│ GC Root: Global variable in native code
│
├─ android.os.Handler$MessengerImpl instance
│ Leaking: UNKNOWN
│ ↓ Handler$MessengerImpl.this$0
│ ~~~~~~
├─ androidx.media.MediaBrowserServiceCompat$ServiceHandler instance
│ Leaking: UNKNOWN
│ this$0 instance of com.bubenheimer.rucksack.d.CW
│ ↓ MediaBrowserServiceCompat$ServiceHandler.this$0
│ ~~~~~~
╰→ com.bubenheimer.rucksack.d.CW instance
Leaking: YES (ObjectWatcher was watching this because com.bubenheimer.rucksack.d.CW received Service#onDestroy()
callback and Service not held by ActivityThread)
key = 0cda35fa-fa79-4035-89ca-6ab496bd1ddc
watchDurationMillis = 5400
retainedDurationMillis = 392
mApplication instance of com.bubenheimer.rucksack.d.D
mBase instance of android.app.ContextImpl
====================================
0 LIBRARY LEAKS
A Library Leak is a leak caused by a known bug in 3rd party code that you do not have control over.
See https://square.github.io/leakcanary/fundamentals-how-leakcanary-works/#4-categorizing-leaks
====================================
0 UNREACHABLE OBJECTS
An unreachable object is still in memory but LeakCanary could not find a strong reference path
from GC roots.
====================================
METADATA
Please include this in bug reports and Stack Overflow questions.
Build.VERSION.SDK_INT: 33
Build.MANUFACTURER: Google
LeakCanary version: 2.10
App process name: com.bubenheimer.rucksack
Class count: 28324
Instance count: 179717
Primitive array count: 132390
Object array count: 25025
Thread count: 39
Heap total bytes: 27055417
Bitmap count: 0
Bitmap total bytes: 0
Large bitmap count: 0
Large bitmap total bytes: 0
Db 1: open /data/user/0/com.bubenheimer.rucksack/databases/com.google.android.datatransport.events
Db 2: open /data/user/0/com.bubenheimer.rucksack/databases/rucksack-5031356898991293088.db
Stats: LruCache[maxSize=3000,hits=32348,misses=41728,hitRate=43%]
RandomAccess[bytes=1991236,reads=41728,travel=35597905162,range=32212305,size=40115227]
Heap dump reason: 1 retained objects, app is visible
Analysis duration: 16991 ms
Heap dump file path: /storage/emulated/0/Download/leakcanary-com.bubenheimer.rucksack/2023-04-25_11-53-35_598.hprof
Heap dump timestamp: 1682438042701
Heap dump duration: 4546 ms
====================================
ga...@google.com <ga...@google.com> #10
I ended up letting the app sit idle for an hour, but the service still would not finalize.
ma...@gmail.com <ma...@gmail.com> #11
I also tried this, but still no finalization:
adb shell am send-trim-memory com.bubenheimer.rucksack:appexternal RUNNING_CRITICAL
ga...@google.com <ga...@google.com> #12
I've dug into this further, and identified a leak in AndroidX code that I was using (
Eliminating this leak lets the MediaBrowserService(Compat) call its finalizer eventually. I assume that the leak-related fixes in API 33 are also essential for reaching this stage.
However, there is still some unidentified holdup between onDestroy() and finalize() in my production app triggering various LeakCanary traces, before finalization after about 30 seconds. (LeakCanary triggers garbage collections, but those do not force finalization in this case.)
I assume the holdup is related to more general problems with service/binder/messenger cleanup. It's an issue, because it makes it very difficult to spot more real problems.
Can anything be done to eliminate these delays?
I am attaching the various leak traces I got from excluding each, one at a time (this is how I eventually found the AndroidX leak).
ma...@gmail.com <ma...@gmail.com> #13
I think the issue can be closed, I am no longer able to reproduce the delayed finalization issue, and I am hoping to switch to media3 MediaSessionService anyway. I have not tried the minimal repro again, though. Ultimately I think the API 33 fixes took care of what was broken here, in addition to avoiding the referenced AndroidX leak.
Thank you for your effort to reopen this.
ma...@gmail.com <ma...@gmail.com> #14
PY Ricau, the guy behind LeakCanary, suggested that there is more to this, and that there are several actual leaks here. I will update this issue with more info as soon as I find some time, I'm in a bit of a crunch right now.
ga...@google.com <ga...@google.com> #15
The 3 LeakCanary leak reports that I attached above point at 2 distinct leaks that are still real, according to PY's analysis from the Github issue here:
Can these leaks be addressed, please?
MediaBrowserServiceCompat$ServiceHandler is an inner class of MediaBrowserServiceCompat (super class of CW) and it's there so that your service can respond to IPC callbacks. It extends Handler and is passed to a Messenger instance created by MediaBrowserServiceCompat in onCreate(), and that Messenger essentially pulls a Binder out of the Handler and passes that binder back to anything calling your service. In other words, every time something binds to your service, the thing that binds to your service is getting an indirect reference to the ServiceHandler which allows it to post messages to that handler which the service will eventually process. However, for this to work, the native framework code keeps a strong native reference locally to the binder until the calling service finalizes the ownership of the binder on its side.
This is actually a common leak pattern in the Android framework: binders are held until the other side runs garbage collection and finalizes the binder on its end, no matter what we're doing with service lifecycle (that's because binders are used beyond services, the only way to be certain the other side won't call is when it doesn't have that pointer). The proper way to handler this is for the service code to finish its handler in onDestroy, or set the reference from the handler to the service to null in onDestroy.
The first and second leak traces are identical, the problem is that MediaBrowserServiceCompat$ServiceHandler has several direct and indirect references to the service.
The last leak is the exact same issue elsewhere, ExtraSession is a stub that won't be GCed until the other side has run its own GC
https://github.com/aosp-mirror/platform_frameworks_support/blob/a9ac247af2afd4115c3eb6d16c05bc92737d6305/media/src/main/java/android/support/v4/media/session/MediaSessionCompat.java#L3413
So these 2 leaks are binder related leaks, and the leaks stay in place until a GC runs in the calling process, and you have no control over that. They really should be fixed.
ga...@google.com <ga...@google.com> #16
I've not been able to reproduce the leak on a device running Android 14 (UDC / API 34).
For unimportant reasons I had to build my own toy app from scratch (using
je...@google.com <je...@google.com> #17
In conclusion, I was able to reproduce on S (Android 12), but unable to reproduce the issue on T (Android 13) or U (Android 14). I'm attaching the project I used for testing in case you find anything wrong.
Can you use that project to reproduce the issue? If yes, we need to figure out what we are doing differently. Also please kindly include a bugreport (running adb bugreport
shortly after the leak is detected) if you are able to repro.
Please assign back to me once you've replied (if you are not able to, ignore).
ga...@google.com <ga...@google.com> #18
I've beefed up your example to make it repro the leaks that I attached in #12. I'll attach the updated example. The relevant changes were:
- Run service & receiver in separate process from Activity.
- Customize LeakCanary to support multiple processes.
- Add some additional media-related code to trigger a leak.
Even when not running the service in a separate process there is a leak in the Activity. I'll attach that one, too. May be a similar root cause. I have not investigated this one.
I am attaching the bugreport, too. I took it right after LeakCanary GC'ed and detected a leak. (About 5 seconds after onDestroy().) But it looks easy to reproduce now.
ma...@gmail.com <ma...@gmail.com> #19
(I did the repro on API 33)
ga...@google.com <ga...@google.com> #20
Also, I don't think non-Googlers are able to reassign an issue, so please take it from here.
ma...@gmail.com <ma...@gmail.com> #21
Thanks. Will provide an update in the next few days.
ga...@google.com <ga...@google.com> #22
Correct me if I'm wrong but the only issue we are aware that still exists is in MediaBrowserServiceCompat, right? (not in the platform MediaBrowserService)
I've sent
Once merged, you should just need to update your androidx.media dependency to pick up the fix.
ma...@gmail.com <ma...@gmail.com> #23
Thanks for the fix.
I'd think that MediaSessionCompat needs a similar fix, based on the leak traces (MediaBrowserServiceCompatLeak4.txt & MediaBrowserActivityLeak.txt) and PY's comments. You can repro MediaBrowserActivityLeak.txt by running the service in the same process as the Activity.
I'll ping PY about possibly chiming in on the code review.
ga...@google.com <ga...@google.com> #24
The change has now been merged. I'll now look into the media session compat issue, which seems to persist.
ma...@gmail.com <ma...@gmail.com> #25
Sorry for the late review. Not sure if you get notifications there, I left a comment:
TL;DR is that using weak refs isn't ideal, you could stick to a strong ref set to null from Service.onDestroy()
ga...@google.com <ga...@google.com>
ma...@gmail.com <ma...@gmail.com> #26
Ack. Will implement the proposed fix.
jw...@gmail.com <jw...@gmail.com> #28
Есть ли утечка информации?
According to translate: Is there any information leak?
No. This is a resources leak, no security issues here.
ga...@google.com <ga...@google.com> #29
Another fix for MediaSessionCompat...ExtraSession here:
Only one pending fix after this change is MediaSessionCompat...MediaSessionStub, after which I plan to mark this as fixed. Still, people should migrate to media3, but at least you can upgrade your MediaSessionCompat dep to get a quick fix of the leaks. Feel free to leave any comments here or in the patch.
dr...@gmail.com <dr...@gmail.com> #30
If there are more leaks to fix in androidx, please kindly file a fresh issue.
jw...@gmail.com <jw...@gmail.com> #31
The following release(s) address this bug.It is possible this bug has only been partially addressed:
androidx.media:media:1.7.0-beta01
dr...@gmail.com <dr...@gmail.com> #32
Hi im wondering if the leak happening in this issue on media3's issue tracker
is related to this.
By taking UAMP and having the MusicServiceConnection
be a Dagger @Singleton
, the MusicService
is leaked with a very similar stack trace that is exposed here, which contains only stacktraces from androidx.media
(until the MusicService
, that is):
====================================
HEAP ANALYSIS RESULT
====================================
1 APPLICATION LEAKS
References underlined with "~~~" are likely causes.
Learn more at https://squ.re/leaks.
43381 bytes retained by leaking objects
Signature: 80f093d135adc2b278b02ca2f66fbd46aaa36bea
┬───
│ GC Root: Global variable in native code
│
├─ android.support.v4.media.session.MediaSessionCompat$MediaSessionImplApi21$ExtraSession instance
│ Leaking: UNKNOWN
│ Retaining 6,7 MB in 1826 objects
│ ↓ MediaSessionCompat$MediaSessionImplApi21$ExtraSession.this$0
│ ~~~~~~
├─ android.support.v4.media.session.MediaSessionCompat$MediaSessionImplApi29 instance
│ Leaking: UNKNOWN
│ Retaining 6,7 MB in 1825 objects
│ ↓ MediaSessionCompat$MediaSessionImplApi21.mSessionFwk
│ ~~~~~~~~~~~
├─ android.media.session.MediaSession instance
│ Leaking: UNKNOWN
│ Retaining 1,8 kB in 12 objects
│ mContext instance of com.example.android.uamp.media.MusicService
│ ↓ MediaSession.mContext
│ ~~~~~~~~
╰→ com.example.android.uamp.media.MusicService instance
Leaking: YES (ObjectWatcher was watching this because com.example.android.uamp.media.MusicService received
Service#onDestroy() callback and Service not held by ActivityThread)
Retaining 43,4 kB in 896 objects
key = 11c50fab-5b0c-4267-8c51-ad235a51d861
watchDurationMillis = 5391
retainedDurationMillis = 390
mApplication instance of com.example.android.uamp.UampApplication
mBase instance of android.app.ContextImpl
====================================
`
I really dont see how using @Singleton
is any different from the default:
companion object {
// For Singleton instantiation.
@Volatile
private var instance: MusicServiceConnection? = null
fun getInstance(context: Context, serviceComponent: ComponentName) =
instance ?: synchronized(this) {
instance ?: MusicServiceConnection(context, serviceComponent)
.also { instance = it }
}
}
The issue can be reproduced on this branch of my fork of UAMP:
Which uses Dagger Hilt and removes Cast for simplification.
To reproduce:
- Open UAMP
- Play something
- Swipe the app away in the task manager
- Music Service is leaked.
From this point restarting UAMP also reveals the issue because nothing is loaded as there will be two MusicService instances.
ma...@gmail.com <ma...@gmail.com> #33
Also note that the example uses media 1.7.0 so fixes above should be included already.
ga...@google.com <ga...@google.com> #34
@ke...@gmail.com might be an issue with MediaSessionCompat, but we'll need a fresh ticket to look into this.
ma...@gmail.com <ma...@gmail.com> #35
Should I create that one then?
ga...@google.com <ga...@google.com> #36
ma...@gmail.com <ma...@gmail.com> #37
Looking forward to the integration let us know when you manage to merge it.
Have a nice weekend!
ga...@google.com <ga...@google.com> #38
ma...@gmail.com <ma...@gmail.com> #39
thank you
ga...@google.com <ga...@google.com> #40
ma...@gmail.com <ma...@gmail.com> #41
does this mean this will come out with beta4?
ga...@google.com <ga...@google.com> #42
ja...@gmail.com <ja...@gmail.com> #43
Simply create a "CustomerTestRunner" and override "onCreate" to call "MultiDex.installInstrumentation(context, targetContext)". See this example:
ja...@gmail.com <ja...@gmail.com> #44
yo...@gmail.com <yo...@gmail.com> #45
st...@gmail.com <st...@gmail.com> #47
Can anyone give us an update and an ETA for this ?
We use build tools 26.0.1, gap 3 beta 5, ASTL runner 1.0.1.
st...@gmail.com <st...@gmail.com> #48
ja...@gmail.com <ja...@gmail.com> #49
run new tests.
Jared Burrows
*jaredsburrows@gmail.com <jaredsburrows@gmail.com>*
LinkedIn:
On Thu, Sep 14, 2017 at 12:14 PM, <buganizer-system@google.com> wrote:
dr...@gmail.com <dr...@gmail.com> #50
st...@gmail.com <st...@gmail.com> #51
st...@gmail.com <st...@gmail.com> #52
je...@google.com <je...@google.com> #53
ja...@gmail.com <ja...@gmail.com> #54
[Deleted User] <[Deleted User]> #55
za...@gmail.com <za...@gmail.com> #56
[Deleted User] <[Deleted User]> #57
le...@gmail.com <le...@gmail.com> #58
ga...@google.com <ga...@google.com> #59
ja...@gmail.com <ja...@gmail.com> #60
vy...@pinterest.com <vy...@pinterest.com> #61
cm...@google.com <cm...@google.com>
gl...@fitbit.com <gl...@fitbit.com> #62
cm...@google.com <cm...@google.com> #63
All the changes needed are submitted to the four components (build tools, MultidexTestRunner, AndroidJunitRunner and android gradle plugin) and we'll update this bug as soon as it is released, so it will be in Android Gradle Plugin 3.1.
Note that both the deprecated MultiDexTestRunner and the replacement AndroidJUnitRunner will support legacy multidex test APKs
sz...@gmail.com <sz...@gmail.com> #64
Doing it in 3.1 will require everyone who wants to have multidex for test APK working to start using unstable version of AS and AGP.
zt...@gmail.com <zt...@gmail.com> #65
> `Using multidex to create a test APK is not currently supported.`
cm...@google.com <cm...@google.com>
ga...@google.com <ga...@google.com> #66
ja...@gmail.com <ja...@gmail.com> #67
an...@gmail.com <an...@gmail.com> #68
le...@gmail.com <le...@gmail.com> #69
[Deleted User] <[Deleted User]> #70
[Deleted User] <[Deleted User]> #71
[Deleted User] <[Deleted User]> #72
ga...@google.com <ga...@google.com> #73
You need to use Android plugin for Gradle 3.1.0-alpha04+, any compatible version of Gradle (e.g. 4.4) and BuildTools (e.g. 27.0.3). Multidex library 1.0.2 will be added by the plugin as a dependency automatically. With this, your build will be successful.
To run tests successfully, the test runner needs to support legacy test APK. AndroidJUnitRunner supports that, so you can use that.
ma...@gmail.com <ma...@gmail.com> #74
For example following your suggestion of tl;dr version the test crashes because some files are not found in the main dex file during the app start:
01-09 10:31:06.965 4861-4861/? W/dalvikvm: Class resolved by unexpected DEX: Ltimber/log/Timber$Tree;(0xa75def58):0x99f02000 ref [Lcom/google/devtools/build/android/desugar/runtime/ThrowableExtension;] Lcom/google/devtools/build/android/desugar/runtime/ThrowableExtension;(0xa75def58):0x99caf000
01-09 10:31:06.965 4861-4861/? W/dalvikvm: (Ltimber/log/Timber$Tree; had used a different Lcom/google/devtools/build/android/desugar/runtime/ThrowableExtension; during pre-verification)
01-09 10:31:06.965 4861-4861/? D/AndroidRuntime: Shutting down VM
01-09 10:31:06.965 4861-4861/? W/dalvikvm: threadid=1: thread exiting with uncaught exception (group=0xa66de228)
01-09 10:31:06.975 4861-4861/? E/InstrumentationResultPrinter: Failed to mark test No Tests as finished after process crash
01-09 10:31:06.975 4861-4861/? E/MonitoringInstr: Exception encountered by: Thread[main,5,main]. Dumping thread state to outputs and pining for the fjords.
java.lang.IllegalAccessError: Class ref in pre-verified class resolved to unexpected implementation
at timber.log.Timber$Tree.getStackTraceString(Timber.java:569)
at timber.log.Timber$Tree.prepareLog(Timber.java:544)
at timber.log.Timber$Tree.i(Timber.java:452)
at timber.log.Timber$1.i(Timber.java:288)
at timber.log.Timber.i(Timber.java:63)
Do you have any idea where does this pops out from?
ga...@google.com <ga...@google.com> #75
This seems to be Java 8 specific bug, and I've filled
st...@gmail.com <st...@gmail.com> #76
fu...@gmail.com <fu...@gmail.com> #77
[Deleted User] <[Deleted User]> #78
[Deleted User] <[Deleted User]> #79
[Deleted User] <[Deleted User]> #80
Until recently we had a big module, with all our code + all our instrurmentation tests code. Then we could check and the plugin (3.1.alpha and 3.1) work well to enable multidex in tests apks.
But we recently dissociated this big module: one contains the production code, the other one contains the instrumentation code. And then, the new plugin breaks: we can still a multidex production app, but the instrumentation test apk is not generated. We hit the 65K limit and the build reports this as an issue. Also, the android test don't have a task: transformClassesWithMultidexlistFor<variant>AndroidTest
What can go wrong ?
[Deleted User] <[Deleted User]> #81
* a few classes in production code
* quite a lot of classes of instrumentation tests
The module_apk wires together all other modules that are all library modules.
When adding multidexEnabled to module_apk, the production apk is multidexed, but not the test apk. There is no transform / task for the AndroidTest variant related to multidex.
When adding multidexEnabled to all default configuration of all modules, all of them have both instrumentation and production multidex tasks & transformations, all except module_apk...
We have no idea what is going wrong.
ga...@google.com <ga...@google.com> #82
I've filled
[Deleted User] <[Deleted User]> #83
Execution failed for task ':app:transformClassesWithMultidexlistForLive'.
> com.android.build.api.transform.TransformException: Error while generating the main dex list.
ga...@google.com <ga...@google.com> #84
pe...@layer.com.c-02odbdyf.appstempdomain.goog <pe...@layer.com.c-02odbdyf.appstempdomain.goog> #85
pa...@gmail.com <pa...@gmail.com> #86
ga...@google.com <ga...@google.com> #87
Yes, please file a new bug, and paste the link here. Issue in #78 was due to a custom plugin which would disable multidex. Thanks!
Description
Build #AI-171.3870562, built on April 1, 2017
JRE: 1.8.0_112-release-b736 x86_64
JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
gradle-3.4.1
classpath 'com.android.tools.build:gradle:2.4.0-alpha4'
buildTools : '25.0.1',
compileSdk : 25,
javaVersion: JavaVersion.VERSION_1_8,
minSdk : 16,
targetSdk : 25
Multidex is setup and works fine (compile, assemble and espresso test) with:
classpath 'com.android.tools.build:gradle:2.3.0'
When we bump up to 2.4 alpha 4 we get multidex issue when we try to run the tests:
(I repeat multidex is setup properly and everything works fine on plugin 2.3.0)
This is a scaffold-like very close to our project setup that I created to reproduce various gradle issues we encounter with our enteprise project:
(sadly I did not update it and maintain it in some time I can refresh it if you really need it or feel free to fork or PR)
This is the stacktrace of the issue
This is the command I ran on our project (should be the same on example project I attached)
./gradlew clean connectedNonpayUnitedStatesBleedingDebugAndroidTest --stacktrace
but I repeat I do not know yet does that project compiles even with the new plugin I can update it later on if you need it.