After scrolling through the timelines for a while, Megalodon will start dropping frames, freeze, then crash to home screen. I have tried reinstalling the app and have confirmed that the issue doesn't exist on the official Mastodon app.
This can happen on any timeline. I typically notice this after the app has been running for a coupe of hours.
Looks to me like it's running out of memory, but a dev may be able to advise better. Other apps and the rest of my phone system are unaffected.
Running on a Galaxy S22 Ultra, Android 14, OneUI 6.0
To reproduce
Steps to reproduce the behavior:
Open Megalodon
Scroll through any timeline for a while
Witness app start dropping frames, freeze, then crash.
Does this happen in the official app?
No (Mastodon Play Store latest)
Screenshots and screen recordings
Recording below was captured just after I noticed frame drops.
Megalodon version: 2.1.6+fork.110 (110) (Play Store latest)
Crash log
Click for log
> ```
> 2.1.6+fork.110 (110)
> 2024-01-11T11:07:24.987Z
>
> java.lang.OutOfMemoryError: Failed to allocate a 56 byte allocation with 70496 free bytes and 68KB until OOM, target footprint 536870912, growth limit 536870912; giving up on allocation because <1% of heap free after GC.
> at android.net.Uri.parse(Uri.java:466)
> at me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest.(SourceFile:44)
> at org.joinmastodon.android.ui.CustomEmojiPopupKeyboard$SingleCategoryAdapter.lambda$new$0(SourceFile:242)
> at org.joinmastodon.android.ui.CustomEmojiPopupKeyboard$SingleCategoryAdapter.$r8$lambda$4MiXBTpf0wNyHQhD-Wq1Y-nOQpU(SourceFile:0)
> at org.joinmastodon.android.ui.CustomEmojiPopupKeyboard$SingleCategoryAdapter$$ExternalSyntheticLambda0.apply(SourceFile:0)
> at j$.util.stream.f2.accept(SourceFile:0)
> at j$.util.a.forEachRemaining(SourceFile:0)
> at j$.util.stream.c.c0(SourceFile:0)
> at j$.util.stream.c.F0(Unknown Source:10)
> at j$.util.stream.C0.v(Unknown Source:4)
> at j$.util.stream.c.I0(SourceFile:0)
> at j$.util.stream.m2.collect(SourceFile:0)
> at org.joinmastodon.android.ui.CustomEmojiPopupKeyboard$SingleCategoryAdapter.(SourceFile:242)
> at org.joinmastodon.android.ui.CustomEmojiPopupKeyboard.onCreateView(SourceFile:119)
> at org.joinmastodon.android.ui.PopupKeyboard.ensureView(SourceFile:41)
> at org.joinmastodon.android.ui.PopupKeyboard.getView(SourceFile:47)
> at org.joinmastodon.android.ui.displayitems.EmojiReactionsStatusDisplayItem$Holder.onBind(SourceFile:184)
> at org.joinmastodon.android.ui.displayitems.EmojiReactionsStatusDisplayItem$Holder.onBind(SourceFile:145)
> at me.grishka.appkit.utils.BindableViewHolder.bind(SourceFile:33)
> at org.joinmastodon.android.fragments.BaseStatusListFragment$DisplayItemsAdapter.onBindViewHolder(SourceFile:977)
> at org.joinmastodon.android.fragments.BaseStatusListFragment$DisplayItemsAdapter.onBindViewHolder(SourceFile:961)
> at me.grishka.appkit.utils.MergeRecyclerAdapter.onBindViewHolder(SourceFile:123)
> at me.grishka.appkit.views.UsableRecyclerView$FooterRecyclerAdapter.onBindViewHolder(SourceFile:433)
> at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(SourceFile:7256)
> at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(SourceFile:7339)
> at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(SourceFile:6197)
> at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(SourceFile:6463)
> at androidx.recyclerview.widget.GapWorker.prefetchPositionWithDeadline(SourceFile:287)
> at androidx.recyclerview.widget.GapWorker.flushTaskWithDeadline(SourceFile:344)
> at androidx.recyclerview.widget.GapWorker.flushTasksWithDeadline(SourceFile:360)
> at androidx.recyclerview.widget.GapWorker.prefetch(SourceFile:367)
> at androidx.recyclerview.widget.GapWorker.run(SourceFile:398)
> at android.os.Handler.handleCallback(Handler.java:958)
> at android.os.Handler.dispatchMessage(Handler.java:99)
> at android.os.Looper.loopOnce(Looper.java:230)
> at android.os.Looper.loop(Looper.java:319)
> at android.app.ActivityThread.main(ActivityThread.java:8893)
> at java.lang.reflect.Method.invoke(Native Method)
> at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:608)
> at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103)
> ```
Just got the same thing when opening a random profile after scrolling the federated timeline, only this was an instant crash after failing to load profile posts.
Click for log
> ```
> 2.1.6+fork.110 (110)
> 2024-01-11T12:18:26.358Z
>
> java.lang.OutOfMemoryError: Failed to allocate a 120 byte allocation with 1242432 free bytes and 1213KB until OOM, target footprint 536870912, growth limit 536870912; giving up on allocation because <1% of heap free after GC.
> at java.lang.StringFactory.newStringFromBytes(Native Method)
> at java.lang.StringLatin1.newString(StringLatin1.java:738)
> at java.lang.StringBuilder.toString(StringBuilder.java:474)
> at me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest.(SourceFile:27)
> at me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest.(SourceFile:36)
> at me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest.(SourceFile:44)
> at org.joinmastodon.android.ui.CustomEmojiPopupKeyboard$SingleCategoryAdapter.lambda$new$0(SourceFile:242)
> at org.joinmastodon.android.ui.CustomEmojiPopupKeyboard$SingleCategoryAdapter.$r8$lambda$4MiXBTpf0wNyHQhD-Wq1Y-nOQpU(SourceFile:0)
> at org.joinmastodon.android.ui.CustomEmojiPopupKeyboard$SingleCategoryAdapter$$ExternalSyntheticLambda0.apply(SourceFile:0)
> at j$.util.stream.f2.accept(SourceFile:0)
> at j$.util.a.forEachRemaining(SourceFile:0)
> at j$.util.stream.c.c0(SourceFile:0)
> at j$.util.stream.c.F0(Unknown Source:10)
> at j$.util.stream.C0.v(Unknown Source:4)
> at j$.util.stream.c.I0(SourceFile:0)
> at j$.util.stream.m2.collect(SourceFile:0)
> at org.joinmastodon.android.ui.CustomEmojiPopupKeyboard$SingleCategoryAdapter.(SourceFile:242)
> at org.joinmastodon.android.ui.CustomEmojiPopupKeyboard.onCreateView(SourceFile:119)
> at org.joinmastodon.android.ui.PopupKeyboard.ensureView(SourceFile:41)
> at org.joinmastodon.android.ui.PopupKeyboard.getView(SourceFile:47)
> at org.joinmastodon.android.ui.displayitems.EmojiReactionsStatusDisplayItem$Holder.onBind(SourceFile:184)
> at org.joinmastodon.android.ui.displayitems.EmojiReactionsStatusDisplayItem$Holder.onBind(SourceFile:145)
> at me.grishka.appkit.utils.BindableViewHolder.bind(SourceFile:33)
> at org.joinmastodon.android.fragments.BaseStatusListFragment$DisplayItemsAdapter.onBindViewHolder(SourceFile:977)
> at org.joinmastodon.android.fragments.BaseStatusListFragment$DisplayItemsAdapter.onBindViewHolder(SourceFile:961)
> at me.grishka.appkit.views.UsableRecyclerView$FooterRecyclerAdapter.onBindViewHolder(SourceFile:433)
> at androidx.recyclerview.widget.RecyclerView$Adapter.onBindViewHolder(SourceFile:7256)
> at androidx.recyclerview.widget.RecyclerView$Adapter.bindViewHolder(SourceFile:7339)
> at androidx.recyclerview.widget.RecyclerView$Recycler.tryBindViewHolderByDeadline(SourceFile:6197)
> at androidx.recyclerview.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(SourceFile:6463)
> at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(SourceFile:6303)
> at androidx.recyclerview.widget.RecyclerView$Recycler.getViewForPosition(SourceFile:6299)
> at androidx.recyclerview.widget.LinearLayoutManager$LayoutState.next(SourceFile:2328)
> at androidx.recyclerview.widget.GridLayoutManager.layoutChunk(SourceFile:571)
> at androidx.recyclerview.widget.LinearLayoutManager.fill(SourceFile:1589)
> at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(SourceFile:666)
> at androidx.recyclerview.widget.GridLayoutManager.onLayoutChildren(SourceFile:169)
> at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(SourceFile:4300)
> at androidx.recyclerview.widget.RecyclerView.dispatchLayout(SourceFile:4003)
> at androidx.recyclerview.widget.RecyclerView.onLayout(SourceFile:4569)
> at android.view.View.layout(View.java:25737)
> at android.view.ViewGroup.layout(ViewGroup.java:6818)
> at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
> at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
> at android.view.View.layout(View.java:25737)
> at android.view.ViewGroup.layout(ViewGroup.java:6818)
> at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
> at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
> at android.view.View.layout(View.java:25737)
> at android.view.ViewGroup.layout(ViewGroup.java:6818)
> at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1891)
> at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1729)
> at android.widget.LinearLayout.onLayout(LinearLayout.java:1638)
> at android.view.View.layout(View.java:25737)
> at android.view.ViewGroup.layout(ViewGroup.java:6818)
> at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
> at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
> at android.view.View.layout(View.java:25737)
> at android.view.ViewGroup.layout(ViewGroup.java:6818)
> at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
> at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
> at android.view.View.layout(View.java:25737)
> at android.view.ViewGroup.layout(ViewGroup.java:6818)
> at androidx.recyclerview.widget.RecyclerView$LayoutManager.layoutDecoratedWithMargins(SourceFile:9880)
> at androidx.recyclerview.widget.LinearLayoutManager.layoutChunk(SourceFile:1687)
> at androidx.recyclerview.widget.LinearLayoutManager.fill(SourceFile:1589)
> at androidx.recyclerview.widget.LinearLayoutManager.onLayoutChildren(SourceFile:666)
> at androidx.recyclerview.widget.RecyclerView.dispatchLayoutStep2(SourceFile:4300)
> at androidx.recyclerview.widget.RecyclerView.dispatchLayout(SourceFile:4003)
> at androidx.recyclerview.widget.RecyclerView.onLayout(SourceFile:4569)
> at android.view.View.layout(View.java:25737)
> at android.view.ViewGroup.layout(ViewGroup.java:6818)
> at androidx.viewpager2.widget.ViewPager2.onLayout(SourceFile:523)
> at android.view.View.layout(View.java:25737)
> at android.view.ViewGroup.layout(ViewGroup.java:6818)
> at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
> at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
> at android.view.View.layout(View.java:25737)
> at android.view.ViewGroup.layout(ViewGroup.java:6818)
> at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1891)
> at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1729)
> at android.widget.LinearLayout.onLayout(LinearLayout.java:1638)
> at android.view.View.layout(View.java:25737)
> at android.view.ViewGroup.layout(ViewGroup.java:6818)
> at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
> at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
> at org.joinmastodon.android.ui.views.CustomScrollView.onLayout(SourceFile:1686)
> at android.view.View.layout(View.java:25737)
> at android.view.ViewGroup.layout(ViewGroup.java:6818)
> at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
> at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
> at android.view.View.layout(View.java:25737)
> at android.view.ViewGroup.layout(ViewGroup.java:6818)
> at androidx.swiperefreshlayout.widget.SwipeRefreshLayout.onLayout(SourceFile:671)
> at android.view.View.layout(View.java:25737)
> at android.view.ViewGroup.layout(ViewGroup.java:6818)
> at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
> at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
> at android.view.View.layout(View.java:25737)
> at android.view.ViewGroup.layout(ViewGroup.java:6818)
> at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
> at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
> at android.view.View.layout(View.java:25737)
> at android.view.ViewGroup.layout(ViewGroup.java:6818)
> at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1891)
> at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1729)
> at android.widget.LinearLayout.onLayout(LinearLayout.java:1638)
> at android.view.View.layout(View.java:25737)
> at android.view.ViewGroup.layout(ViewGroup.java:6818)
> at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
> at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
> at android.view.View.layout(View.java:25737)
> at android.view.ViewGroup.layout(ViewGroup.java:6818)
> at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
> at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
> at android.view.View.layout(View.java:25737)
> at android.view.ViewGroup.layout(ViewGroup.java:6818)
> at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
> at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
> at android.view.View.layout(View.java:25737)
> at android.view.ViewGroup.layout(ViewGroup.java:6818)
> at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
> at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
> at android.view.View.layout(View.java:25737)
> at android.view.ViewGroup.layout(ViewGroup.java:6818)
> at android.widget.FrameLayout.layoutChildren(FrameLayout.java:332)
> at android.widget.FrameLayout.onLayout(FrameLayout.java:270)
> at com.android.internal.policy.DecorView.onLayout(DecorView.java:1075)
> at android.view.View.layout(View.java:25737)
> at android.view.ViewGroup.layout(ViewGroup.java:6818)
> at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:5193)
> at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:4466)
> at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:3239)
> at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:11197)
> at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1650)
> at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1659)
> at android.view.Choreographer.doCallbacks(Choreographer.java:1129)
> at android.view.Choreographer.doFrame(Choreographer.java:1055)
> at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1622)
> at android.os.Handler.handleCallback(Handler.java:958)
> at android.os.Handler.dispatchMessage(Handler.java:99)
> at android.os.Looper.loopOnce(Looper.java:230)
> at android.os.Looper.loop(Looper.java:319)
> at android.app.ActivityThread.main(ActivityThread.java:8893)
> at java.lang.reflect.Method.invoke(Native Method)
> at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:608)
> at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1103)
> ```
Describe the bug
After scrolling through the timelines for a while, Megalodon will start dropping frames, freeze, then crash to home screen. I have tried reinstalling the app and have confirmed that the issue doesn't exist on the official Mastodon app.
This can happen on any timeline. I typically notice this after the app has been running for a coupe of hours.
Looks to me like it's running out of memory, but a dev may be able to advise better. Other apps and the rest of my phone system are unaffected.
Running on a Galaxy S22 Ultra, Android 14, OneUI 6.0
To reproduce
Steps to reproduce the behavior:
Does this happen in the official app?
No (Mastodon Play Store latest)
Screenshots and screen recordings
Recording below was captured just after I noticed frame drops.
https://github.com/sk22/megalodon/assets/88419550/2d693e40-3716-4062-abaa-83b25f09e9ca
Version
Megalodon version: 2.1.6+fork.110 (110) (Play Store latest)
Crash log
Click for log
> ``` > 2.1.6+fork.110 (110) > 2024-01-11T11:07:24.987Z > > java.lang.OutOfMemoryError: Failed to allocate a 56 byte allocation with 70496 free bytes and 68KB until OOM, target footprint 536870912, growth limit 536870912; giving up on allocation because <1% of heap free after GC. > at android.net.Uri.parse(Uri.java:466) > at me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest.