我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Android程序内存忽高忽低怎么解决

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Android程序内存忽高忽低怎么解决

本篇内容介绍了“Android程序内存忽高忽低怎么解决”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

一:背景

讲故事

昨天继续还技术债,优化一轮后的程序拉到线上后内存继续忽高忽低,低的时候20G,高的时候30G,过了一会又下降了几个G,毫无疑问,程序中有什么集合或者什么操作占用了大量内存,所以准备在28,29G的时候抓dump分析分析。

二:解决思路

从快照中找问题就像看病一样,根据病象猜测,都有一套经验可循。

把托管堆中>10M的对象找出来

通常应对大集合从托管堆入手最简单,看哪个类型占用空间大,基本就是它出问题了,为了避免把所有类型都打出来,这里设置一下过滤,把小于10M都踢掉, 可以用 !dumpheap -stat -min 10240,把敏感对象脱敏掉。


0:000> !dumpheap -stat -min 10240
Statistics:
             MT    Count    TotalSize Class Name
00007ffe094e6fc0        4       523776 System.Object[]
00007ffe094e6948        6      7179822 System.String
00007ffe0780da08       33     46514160 System.Collections.Generic.Dictionary`2+Entry[[System.Int32, mscorlib],[System.Collections.Generic.HashSet`1[[System.Int32, mscorlib]], System.Core]][]
00007ffe09f95f40      250    188739344 System.Collections.Generic.Dictionary`2+Entry[[System.Int32, mscorlib],[System.Int32, mscorlib]][]
00007ffe094ec988       18    540828823 System.Byte[]
00007ffe07802da8     1620    622578672 System.Linq.Set`1+Slot[[System.Int32, mscorlib]][]
000001bc0452e600     1389   1038494910      Free
00007ffe094baf50       68   1128274800 System.Collections.Generic.Dictionary`2+Entry[[System.Int32, mscorlib],[System.DateTime, mscorlib]][]
00007ffe094e9220     2224   1513951832 System.Int32[]
00007ffe07819df8     2232   1668042480 System.Collections.Generic.HashSet`1+Slot[[System.Int32, mscorlib]][]
00007ffe094c8510      226   1672164568 System.Int64[]
00007ffdab8676e8     1137   1901228880 System.Collections.Generic.HashSet`1+Slot[[System.Int64, mscorlib]][]
00007ffdab89b3b0      136   1986723840 System.Linq.Set`1+Slot[[System.Int64, mscorlib]][]
Total 13321 objects

找出堆中可疑的对象

因为程序启动后作为内存数据库,所以有包含指定类的大集合对象很正常,倒数第7行有一个Dictionary<int,Datetime> 占用空间挺大的,1128274800/1024/1024=1G,这个貌似不是基础数据,应该是中间变量,方法表地址为00007ffe094baf50, 通过它可以找到这68个集合的内存地址。


0:028> !dumpheap -mt 00007ffe094baf50
        Address               MT     Size  
000001c2f262a708 00007ffe094baf50 69438000    
000001c1bb8e1020 00007ffe094baf50 16147872    
000001c1bce04760 00007ffe094baf50 33486336    
000001c37e8f1020 00007ffe094baf50 143987328    
000001c44e8f1020 00007ffe094baf50 287974800    
000001c3c419b268 00007ffe094baf50 16147872  
000001c3f6b9ac28 00007ffe094baf50 16147872    
000001c467336fa0 00007ffe094baf50 33486336    
000001c46f3fa760 00007ffe094baf50 69438000  
000001c489df3668 00007ffe094baf50 16147872    
000001c494166828 00007ffe094baf50 33486336    
000001c4a68f1020 00007ffe094baf50 69438000  
000001c4d4c5c290 00007ffe094baf50 16147872    
000001c4da8f1058 00007ffe094baf50 33486336    
000001c4de8f1020 00007ffe094baf50 69438000
000001c5028f1058 00007ffe094baf50 33486336    
000001c5068f1020 00007ffe094baf50 33486336
...

下一步挑几个大的 Dictionary 看看,比如这一行: 000001c44e8f1020 00007ffe094baf50 287974800,计算一下size:279M。

寻找集合所在的代码块

字典占用279M我是知道了,但怎么知道这个字典是在哪一个代码块呢? 要寻找答案也容易,通过!gcroot 找到它的引用根,通过引用链就可以找到它的代码区块,简直不要太实用


0:000> !gcroot 000001c4de8f1020
Thread 2da8:
   00000017f4c7e5d0 00007ffdab758ca1 xxxx.xxxx.xxxx.GetFlowAwayCustomer(Int32, System.String, System.Collections.Generic.Dictionary`2<System.String,System.Collections.Generic.List`1<xxxx>>)
       rbp-238: 00000017f4c7e628
           ->  000001c3d5c1bdf0 System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[System.Collections.Generic.Dictionary`2[[System.Int32, mscorlib],[System.DateTime, mscorlib]], mscorlib]]
           ->  000001c3d8de7d10 System.Collections.Generic.Dictionary`2+Entry[[System.String, mscorlib],[System.Collections.Generic.Dictionary`2[[System.Int32, mscorlib],[System.DateTime, mscorlib]], mscorlib]][]
           ->  000001c3d8d58630 System.Collections.Generic.Dictionary`2[[System.Int32, mscorlib],[System.DateTime, mscorlib]]
           ->  000001c4de8f1020 System.Collections.Generic.Dictionary`2+Entry[[System.Int32, mscorlib],[System.DateTime, mscorlib]][]

从上面引用链可以看到三点信息:

<1> 当前字典在 2da8 线程上

<2> 字典在 GetFlowAwayCustomer 方法中,大概可以看出是计算流失客户的。

<3> 调用链顶部是最大的集合 Dictionary<string,Ditionary<int,DateTime>> ,address:000001c3d5c1bdf0

寻找更多信息

<1> 挖字典内容

有了最大的字典,我们来看看最大字典Dictionary<string,Ditionary<int,DateTime>> 占用的内存大小。


0:000> !objsize 000001c3d5c1bdf0
sizeof(000001c3d5c1bdf0) = 340008256 (0x14441d40) bytes (System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[System.Collections.Generic.Dictionary`2[[System.Int32, mscorlib],[System.DateTime, mscorlib]], mscorlib]])

根据sizeof(000001c3d5c1bdf0) = 340008256 (0x14441d40) bytes 计算一下:324M,尼玛,这都是其中一个字典,难怪内存忽高忽低,现在大家肯定特别想知道里面有啥东西,可以用 da -> !do 去内部集合看一下。


0:000> !da -length 1 -start 1 -details 000001c3d8de7d10
Name:        System.Collections.Generic.Dictionary`2+Entry[[System.String, mscorlib],[System.Collections.Generic.Dictionary`2[[System.Int32, mscorlib],[System.DateTime, mscorlib]], mscorlib]][]
MethodTable: 00007ffdab940650
EEClass:     00007ffdab9405b8
Size:        192(0xc0) bytes
Array:       Rank 1, Number of elements 7, Type VALUETYPE
Element Methodtable: 00007ffdab940520
[1] 000001c3d8de7d38
   Name:        System.Collections.Generic.Dictionary`2+Entry[[System.String, mscorlib],[System.Collections.Generic.Dictionary`2[[System.Int32, mscorlib],[System.DateTime, mscorlib]], mscorlib]]
   MethodTable: 00007ffdab940520
   EEClass:     00007ffe08e92920
   Size:        40(0x28) bytes
   File:        C:\Windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
   Fields:
                     MT    Field   Offset                 Type VT     Attr            Value Name
       00007ffe094e9288  4003474       10             System.Int32      1     instance             58671583     hashCode
       00007ffe094e9288  4003475       14             System.Int32      1     instance                   -1     next
       00007ffe094ebf10  4003476        0           System.__Canon      0     instance     000001c2cec43610     key
       00007ffe094ebf10  4003477        8           System.__Canon      0     instance     000001c3d7b45370     value
0:000> !do 000001c3d7b45370    
Name:        System.Collections.Generic.Dictionary`2[[System.Int32, mscorlib],[System.DateTime, mscorlib]]
MethodTable: 00007ffe094b9ec8
EEClass:     00007ffe08e9d528
Size:        80(0x50) bytes
File:        C:\Windows\Microsoft.Net\assembly\GAC_64\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll
Fields:
             MT    Field   Offset                 Type VT     Attr            Value Name
00007ffe094e9220  4001858        8       System.Int32[]  0 instance 000001c46e8f1020 buckets
00007ffe094baf50  4001859       10 ...ime, mscorlib]][]  0 instance 000001c46f3fa760 entries
00007ffe094e9288  400185a       38         System.Int32  1 instance          2512598 count
00007ffe094e9288  400185b       3c         System.Int32  1 instance          3194430 version
00007ffe094e9288  400185c       40         System.Int32  1 instance               -1 freeList
00007ffe094e9288  400185d       44         System.Int32  1 instance                0 freeCount
00007ffe094dabb8  400185e       18 ...Int32, mscorlib]]  0 instance 000001bc06272ab8 comparer
00007ffe0a0463e0  400185f       20 ...eTime, mscorlib]]  0 instance 0000000000000000 keys
00007ffe0a046258  4001860       28 ...eTime, mscorlib]]  0 instance 0000000000000000 values
00007ffe094e6f28  4001861       30        System.Object  0 instance 0000000000000000 _syncRoot

可以看到大字典中7个元素,然后我挑了一个内嵌Dictionary,可以看到这个内嵌字典的count=251w,里面的details我就不输出了。

<2> 挖线程栈

有了字典内容,大家继续看一下此时这个线程 [2da8] 在做什么?


0:028> ~~[2da8]s
ntdll!NtWaitForSingleObject+0x14:
00007ffe`28646124 c3              ret
0:028> !clrstack
OS Thread Id: 0x2da8 (28)
       Child SP               IP Call Site
00000017f4c7e388 00007ffe28646124 [HelperMethodFrame: 00000017f4c7e388]
00000017f4c7e4f0 00007ffe09e48e52 System.Collections.Generic.Dictionary`2[[System.Int32, mscorlib],[System.DateTime, mscorlib]].Resize(Int32, Boolean)
00000017f4c7e560 00007ffe09316c65 System.Collections.Generic.Dictionary`2[[System.Int32, mscorlib],[System.DateTime, mscorlib]].Insert(Int32, System.DateTime, Boolean)

Android程序内存忽高忽低怎么解决

大家应该知道,有扩容就有虚占内存。

“Android程序内存忽高忽低怎么解决”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Android程序内存忽高忽低怎么解决

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Android程序内存忽高忽低怎么解决

本篇内容介绍了“Android程序内存忽高忽低怎么解决”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一:背景1. 讲故事昨天继续还技术债,优
2023-06-03

qt程序内存泄露怎么解决

解决Qt程序内存泄漏的方法如下:1. 使用对象的父子关系:在创建对象时,将对象的父对象设置为合适的父对象。这样,当父对象被销毁时,它的所有子对象也会被自动销毁,从而避免内存泄漏。2. 使用智能指针:使用std::unique_ptr或std
2023-08-18

vps主机内存频率太低怎么解决

要解决VPS主机内存频率太低的问题,可以考虑以下几个方法:1. 升级VPS主机的内存条:联系VPS主机提供商,了解是否可以升级内存。如果可以,购买更高频率的内存条并替换原有的内存条。2. 优化VPS主机的内存使用:通过优化VPS主机上的应用
2023-08-11

Android内存泄露怎么解决

解决Android内存泄露问题的方法有以下几种:1. 避免长生命周期的引用:确保在不使用时及时释放对象的引用,如Activity中的Context、Fragment中的View等。可以使用WeakReference或者弱引用来解决这个问题。
2023-09-29

win8.1系统忽然没有声音了怎么办?win8.1系统忽然没有声音的两种解决方法图文教程

有些时候win8.1系统会出现忽然没有声音的问题,无论怎样滑动音量条都没用,只能重启,怎么回事呢?导致win8.1系统忽然没有声音的原因有很多,小编收集一些相关win8.1系统忽然没有声音的解决方法,接下来编程网的小编和大家分享win8.1
2022-06-04

android 退出程序解决内存释放的问题

做Android项目的时候发现一个问题:当应用程序退出了,点击"设置"查看应用程序,界面显示着可以点击"强制关闭". 我认为造成这样的原因是还有开启的activity没有被destroy,然后做调试,之后发现开启的activity应该是全部
2022-06-06

android handler内存泄漏怎么解决

在Android中,Handler的使用很容易引发内存泄漏问题。以下是一些解决内存泄漏的方法:1. 使用静态内部类:将Handler定义为Activity的静态内部类,并将Activity的弱引用保存在Handler中,这样可以避免Hand
2023-09-15

win11内存占用高怎么解决

本篇内容主要讲解“win11内存占用高怎么解决”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“win11内存占用高怎么解决”吧!win11内存占用高解决方法:1、首先按下键盘“Win+R”,打开运
2023-06-30

centos7内存占用过高怎么解决

当CentOS 7的内存占用过高时,可以尝试以下方法来解决问题:查看内存占用:使用命令free -h或top来查看当前系统的内存使用情况,了解哪些进程占用了大量的内存。优化程序:如果发现某个特定的进程占用了大量内存,可以尝试优化该程序,减少
2023-10-23

android内存溢出和内存泄漏问题怎么解决

Android内存溢出和内存泄漏是常见的问题,可以通过以下方法来解决:1. 使用内存分析工具:可以使用Android Studio自带的Memory Profiler或者第三方工具(如MAT、LeakCanary)来分析和监测内存使用情况,
2023-08-26

mysql内存使用率过高怎么解决

如果MySQL内存使用率过高,可以尝试以下方法来解决:优化数据库配置:检查MySQL配置文件,根据实际情况调整缓冲区大小、连接数等参数,以减少内存使用。优化查询语句:优化查询语句,避免不必要的全表扫描和索引扫描,提高查询效率,减少内存占用。
mysql内存使用率过高怎么解决
2024-04-09

win102004内存占用率过高怎么解决

这篇文章主要介绍“win102004内存占用率过高怎么解决”,在日常操作中,相信很多人在win102004内存占用率过高怎么解决问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”win102004内存占用率过高怎
2023-07-01

android内存泄露怎么查看和解决

Android内存泄露是指内存中的对象无法被及时释放,导致内存占用过高,影响应用的性能和稳定性。以下是查看和解决Android内存泄露问题的一些方法:使用Android Studio的内存监视工具:在Android Studio中,可以使用
android内存泄露怎么查看和解决
2024-03-13

java堆内存使用率过高怎么解决

Java堆内存使用率过高可能是由于程序中存在内存泄漏、内存分配不合理或者程序存在大量的GC问题等原因导致的。下面是一些解决方法:1. 检查内存泄漏:使用内存分析工具(如MAT、jvisualvm等)来检查程序中是否存在内存泄漏问题,及时释放
2023-09-27

电脑svchost占用内存过高怎么解决

本篇内容主要讲解“电脑svchost占用内存过高怎么解决”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“电脑svchost占用内存过高怎么解决”吧!svchost占用内存过高解决方法:1、找到计算
2023-07-01

怎么用Node.js编写内存效率高的应用程序

这篇文章主要介绍怎么用Node.js编写内存效率高的应用程序,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!问题:大文件复制如果有人被要求用 NodeJS 写一段文件复制的程序,那么他会迅速写出下面这段代码:const
2023-06-14

java多线程内存泄漏怎么解决

Java中的内存泄漏问题通常是由于没有正确释放对象所引用的资源而导致的。下面是一些解决内存泄漏问题的常见方法:及时释放资源:在使用完对象后,要确保及时释放它所占用的资源,如关闭文件、数据库连接、网络连接等。可以使用try-finally语句
2023-10-27

Win10电脑内存占用过高怎么办 win10电脑内存占用高的解决方法

一些用了几年或配置比较低的电脑,在如今使用中经常会出现CPU和内存占用太高,而出现卡顿等问题。今天小编以Win10系统为例,教大家如何优化电脑内存占用高的问题,尽可能提升电脑的流畅性。Win10电脑内存占用太高解决办法 其实,很多人在使用电
2023-05-22

win7系统下svchost占用内存过高怎么解决

在Windows 7系统下,如果svchost进程占用内存过高,可以尝试以下解决方法:1. 打开任务管理器:按下Ctrl + Shift + Esc组合键,或者右键点击任务栏空白处,选择“任务管理器”。2. 在任务管理器中,切换到“进程”选
2023-09-02

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录