当前位置: 首页 > news >正文

Android OOM问题定位、内存优化

一、OOM

out of memory:简称OOM,内存溢出,申请的内存大于剩余的内存而抛出的异常。

对于Android平台,广义的OOM主要是以下几种类型

  • Java
  • Native
  • Thread

线程数的上限默认为32768,部分华为设备的限制是500通常1000左右就会触发VSS OOM。因此Thread 00M其实也是VSS OOM的一种表现形式。

引起线程OOM原因:1.文件描述符不够 2.地址空间不足

  • File Descriptor

Android 9.0以前fd也是比较宝贵的资源,每个进程的上限只有1024,9.0开始增加到了32768。

  • JNI Reference

JNl Reference 0OM可以通过logcat初步定位。

常用工具:

1、LeakCanary

val refWatcher: RefWatcher? = TestApp.getRefWatcher(activity)
refWatcher?.watch(activity);//检测是否有泄露,即触发GC回收,看activity是否被回收,没有被回收就是泄露了。

二、常见的几种内存泄漏

1、长生命周期引用短生命周期2、资源没有释放
单例造成的内存泄露

非静态内部类创建静态实例造成的内存泄露

Handler造成的内存泄露

线程造成的内存泄露

Webview造成的内存泄露

三、OOM的原因,以及如何定位OOM

OOM产生的原因:

1、一次性申请的太多

更改申请对象数量
2.内存资源耗尽未释放

找到未释放的对象进行释放
3.本身资源不够
jmap -heap 查看堆信息

如何优化内存

1、减小对象的内存占用

2、内存对象的复用

3、避免对象的内存泄露

如何定位OOM

如何通过dump定位
系统已经OOM挂了
提前设置-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=
系统运行中还未OOM
导出dump文件:jmap -dump:format=b,file=xushu.hprof 14660Arthas
结合ivisualvm 进行调试
查看最多跟业务有关对象->找到GCRoot ->查看线程栈

四、GC回收原理

GCRoot——对象可达性分析

可回收对象的判定
通过一系列称为“GC Roots”的对象作为起始点,从这些节点向下搜索,搜索所有的引用链,当一个对象到GC Roots没有任何引用链(即GC Roots到对象不可达)时,则证明此对象是不可用的。

五、Java内存分配模型

GCRoot是:方法区Method Area、虚拟机栈VM Stack(即本地变量)、本地方法栈Native Method(即静态变量和常量) Stack中的变量。如GCRoot中变量有对堆中对象的引用,gc则不回收堆中的该对象,如堆中对象无来自GCRoot的引用,则回收该对象。例如,B b = new B();对象b为引用存于虚拟机栈VM Stack中,new出的B对象存于堆中。

六、Android profiler——dump内存快照分析

双击打开设备Downloads文件夹下hprof文件,文件信息在profiler中被显示。

shallow size浅堆和Retain size深堆的区别

shallow size(浅堆)是指对象本身占用内存的情况

Retain size(深堆)是指对象以及对象关联其他引用占用内存的总和。即,对象本身被GC回收后,导致其他对象同时也被GC回收,这些被回收的所有对象占用内存总和。

如下举例:

1、对象A,B,C内存占用情况如下,A的shallow size是10M,Retain size是30M

1、对象A,B,C,D内存占用情况如下

A的shallow size是10M,Retain size是20M

B的shallow size是10M,Retain size是10M

C的shallow size是10M,Retain size是10M

D的shallow size是10M,Retain size是10M

七、Java的四种引用
1.强引用(Strong Reference)在代码中普遍使用的,类似Person person=new Person();如果一个对象具有强引用,则无论在什么情况下,GC都不会回收被引用的对象。当内存空间不足时,JAVA虚拟机宁可抛出outOfMemoryError终止应用程序也不会回收具有强引用的对象。
2.软引用(Soft Reference)表示一个对象处在有用但非必须的状态。如果一个对象具有软引用,在内存空间充足时,GC就不会回收该对象;当内存空间不足时,GC会回收该对象的内存(回收发生在0utofMemoryError之前)。软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被GC回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中,以便在恰当的时候将该软引用回收。但是由于GC线程的优先级较低,通常手动调用system.gc()并不能立即执行GC,因此弱引用所引用的对象并不一定会被马上回收。

3.弱引用(Weak Reference)用来描述非必须的对象。它类似软引用,但是强度比软引用更弱一些:弱引用具有更短的生命,GC在扫描的过程中,一旦发现只具有被弱引用关联的对象,都会回收掉被弱引用关联的对象。换言之,无论当前内存是否紧缺,GC都将回收被弱引用关联的对象。

4.虚引用(Phantom Reference)虚引等同于没有引用,这意味着在任何时候都可能被GC回收,设置虚引用的目的是为了被虚引用关联的对象在被垃圾回收器回收时,能够收到一个系统通知。(被用来跟踪对象被GC回收的活动)虚引用和弱引用的区别在于:虚引用在使用时必须和引用队列(ReferenceQueue)联合使用,其在GC回收期间的活动如下:ReferenceQueue queue=new ReferenceQueue();PhantomReference pr=new PhantomReference(obiect.queue)也即是GC在回收一个对象时,如果发现该对象具有虚引用,那么在回收之前会首先该对象的虚引用加入到与之关联的引用队列中。程序可以通过判断引用队列中是否已经加入虚引用来了解被引用的对象是否被GC回收。

软引用和弱引用的区别如下:

软引用:gc扫到,不一定回收,内存不足时才回收

弱引用:gc扫到,就回收。

弱引用和引用队列的关系如下:

泄露了:弱引用没有加入引用队列,故引用队列为空

没有泄露:弱引用加入引用队列,故引用队列不为空

八、Java新生代,老年代和永久代的区别

在Java虚拟机(JVM)的内存管理中,堆内存通常被划分为几个不同的区域,以便更有效地管理和回收内存。以下是新生代(Young Generation)、老年代(Old Generation)和永久代/元空间(PermGen/Metaspace)的具体含义:

1. 新生代 (Young Generation)
- 新生代是Java堆内存的一部分,主要用于存储新创建的对象。对象在首次分配内存时会被放入新生代。

- 新生代的特点是大量对象在此快速生成并很快消亡,因此这里的垃圾回收(Garbage Collection, GC)非常频繁,通常称为Minor GC或Young GC。

- 新生代进一步细分为 Eden 区、两个 Survivor 区(例如:From 和 To 区),每次GC后,存活下来的对象会被复制到另一个Survivor区,若对象经历了一定次数的GC还存活,则晋升至老年代。

2. 老年代 (Old Generation)
- 老年代也是Java堆内存的一部分,主要存放经过一定时间周期仍然存活下来的对象,即经历过多次新生代GC仍然没有被回收的对象。

- 对象一旦晋升到老年代,意味着它们生命周期较长,老年代的垃圾回收相对较少,但是一旦发生,通常会是Major GC或Full GC,这类GC会比Minor GC更加耗时且影响更大。

3. 永久代 (PermGen)
- 在JDK 8及之前版本的HotSpot JVM中,永久代是方法区的一个实现,用于存储类信息、常量池、静态变量、方法字节码以及其他运行时常驻数据结构。

- 永久代的空间有限,如果加载了大量的类或者反射操作过于频繁,可能导致永久代空间不足,从而抛出`java.lang.OutOfMemoryError: PermGen space`异常。

4. 元空间 (Metaspace)
:
- 自JDK 8开始,HotSpot JVM取消了永久代的概念,并引入了一个新的内存区域叫做元空间(Metaspace)。

- 元空间同样用于存储类元数据信息,但它位于本地内存(Native Memory)而非堆内存中,这意味着它的大小不再受到JVM堆大小的限制,而受限于系统的实际可用内存。

- 当类元数据的总量超过了指定阈值或者系统内存限制时,将会触发类卸载机制,并可能出现`java.lang.OutOfMemoryError: Metaspace`异常。

总结起来,新生代和老年代是用来区分对象生命周期长短进而进行高效内存回收的堆内存区域,而永久代在旧版JVM中是方法区的一种实现方式,存储类和方法级别的元数据;在新版JDK中,这部分功能由元空间替代。

九、JVM出现OOM异常会导致进程挂掉吗?
当一个线程在执行代码的过程中,大概率需要创建对象,而创建对象就需要分配内存,如果VM可用内存不够时会进行垃圾回收,如果垃圾回收完了之后内存还是不够就会地出OutOfMemoryEror,如果没有捕获OutOfMemoryError,那么就像抛出一个普通异常一样会导致线程停掉,如果捕获了OutOfMemoryEror,那么线程可能就不会亭掉,其实不管当前线程会不会停掉,跟进程会不会挂掉没有直接关系,也就是出现,了OutOfMemgrvEror最多只会导致线程停掉,如果一个讲程里面的所有非守护线程都亭掉了,那么进程才会停掉,或者进程占了操作系统的过多内存,那么这个进程可能会被操作系统关闭掉。

                        
参考:https://blog.csdn.net/pengweid/article/details/137125832

参考:彻底解决Android开发中的OOM问题,竟然一节课就够了_哔哩哔哩_bilibili

参考:美团面试题:一个线程 OOM 后,其他线程还能运行吗?_哔哩哔哩_bilibili

相关文章:

Android OOM问题定位、内存优化

一、OOM out of memory:简称OOM,内存溢出,申请的内存大于剩余的内存而抛出的异常。 对于Android平台,广义的OOM主要是以下几种类型 JavaNativeThread 线程数的上限默认为32768,部分华为设备的限制是500通常1000左右…...

棋盘(c++题解)

题目描述 有一个m m的棋盘,棋盘上每一个格子可能是红色、黄色或没有任何颜色的。你现在要从棋盘的最左上角走到棋盘的最右下角。 任何一个时刻,你所站在的位置必须是有颜色的(不能是无色的) ,你只能向上、下、 左、右…...

滑动窗口例题

一、209:长度最小的子数组 209:长度最小的子数组 思路:1、暴力解法:两层for循环遍历,当sum > target时计算子数组长度并与result比较,取最小的更新result。提交但是超出了时间限制。 class Solution {public int minSubArray…...

智过网:注册安全工程师注册有效期与周期解析

在职业领域,各种专业资格认证不仅是对从业者专业能力的认可,也是保障行业安全、规范发展的重要手段。其中,注册安全工程师证书在安全生产领域具有举足轻重的地位。那么,注册安全工程师的注册有效期是多久呢?又是几年一…...

腐蚀Rust 服务端搭建架设个人社区服务器Windows教程

腐蚀Rust 服务端搭建架设个人社区服务器Windows教程 大家好我是艾西,一个做服务器租用的网络架构师也是游戏热爱者。最近在steam发现rust腐蚀自建的服务器以及玩家还是非常多的,那么作为服务器供应商对这商机肯定是不会放过的哈哈哈! 艾西这…...

蓝桥杯备赛:考前注意事项

考前注意事项 1、DevCpp添加c11支持 点击 工具 - 编译选项 中添加&#xff1a; -stdc112、万能头文件 #include <bits/stdc.h>万能头文件的缺陷&#xff1a;y1 变量 在<cmath>中用过了y1变量。 #include <bits/stdc.h> using namespace std;// 错误示例 …...

111111111111

111111111111...

uniapp 卡片勾选

前言 公司的app项目使用的uniapp&#xff0c;项目里有一个可勾选的卡片功能&#xff0c;效果图如下&#xff1a; 找了一圈没找到什么太好的组件&#xff0c;于是就自己简单写了一个&#xff0c;记录一下。避免以后还会用到 代码 <template><view class"card-…...

乐趣Python——文件与数据:挥别乱糟糟的桌面

各位朋友们&#xff0c;今天我们要开启一场非凡的冒险——进入文件操作的世界&#xff01;你知道吗&#xff0c;在你的电脑里&#xff0c;有一个叫做“文件系统”的迷宫&#xff0c;里面藏着各种各样的文件和文件夹&#xff0c;它们就像是迷宫中的宝藏。但有时候&#xff0c;这…...

docker nginx-lua发送post json 请求

环境准备 dockerfile from fabiocicerchia/nginx-lua:1.25.3-ubuntu22.04 run apt-get -qq update && apt-get -qq install luarocks run luarocks install lua-cjson run luarocks install lua-iconv run luarocks install lua-resty-http后台代理服务准备&#xff…...

阿里面试总结 一

写了这些还是不够完整&#xff0c;阿里 字节 卷进去加班&#xff01;奥利给 ThreadLocal 线程变量存放在当前线程变量中&#xff0c;线程上下文中&#xff0c;set将变量添加到threadLocals变量中 Thread类中定义了两个ThreadLocalMap类型变量threadLocals、inheritableThrea…...

多线程(49)定义无锁、阻塞、非阻塞和无等待算法

在并发编程中&#xff0c;理解不同的同步策略——无锁&#xff08;Lock-Free&#xff09;、阻塞&#xff08;Blocking&#xff09;、非阻塞&#xff08;Non-Blocking&#xff09;、无等待&#xff08;Wait-Free&#xff09;——对于设计高效、健壮的多线程应用至关重要。让我们…...

(一)ffmpeg 入门基础知识

一、ffmpeg FFmpeg是一套强大的开源音视频处理工具&#xff0c;能够录制、转换以及流化音视频内容。 FFmpeg是开源的&#xff0c;这意味着它的源代码是公开的&#xff0c;允许任何人使用、修改和分发。它提供了录制、转换以及流化音视频的完整解决方案&#xff0c;支持多种格…...

【软件测试】个人博客系统测试

个人博客系统测试 一、项目背景1.1 技术背景1.2 功能背景 二、 测试用例编写三、自动化测试3.1 什么是自动化测试3.2 通过使用selenium进行自动化测试的编写&#xff08;Java实现&#xff09;3.3 编写测试用例&#xff0c;执行自动化测试3.3.1 输入用户名:test,密码:123&#x…...

20240410解决OK3588-C的核心板刷机之后无法启动的问题

20240410解决OK3588-C的核心板刷机之后无法启动的问题 2024/4/10 19:38 1、编译OK3588的LINUX/Buildroot&#xff1f;forlinxubuntu: ~/3588/OK3588_Linux_fs$ sudo ./build.sh BoardConfig-linuxfs-ok3588.mk 2、进行全编译 forlinxubuntu: ~/3588/OK3588_Linux_fs$ sudo ./bu…...

仅需三步就能成为大语言模型Prompt Engineer提示词工程大神

AI Prompt Engineer(提示词工程)是当下GenAI行业最热门的话题&#xff0c;它是利用有效的AI模型交互提示技术&#xff0c;引导大语言模型生成更高质量、更准确、更相关的回应。相对于预训练和微调&#xff0c;提示词工程不需要标注数据和训练模型&#xff0c;极大的节约了时间和…...

RuleEngine规则引擎底层改造AviatorScript 之公式规则

前情提要&#xff0c;看上一个文章&#xff0c;具体要实现的效果就是 当然上来的问题就是前端的问题&#xff0c;这个框首先他们用的是富文本&#xff0c;富文本传到后台的结果是前端脚本&#xff0c;带着h5的标签&#xff0c;后面改成了这个&#xff0c;当时这个东西其实和后…...

Vue项目(H5)与微信小程序来回跳转

新建H5页面 在小程序里面新建一个名为H5的文件夹&#xff0c;以及H5页面 H5.WXML <web-view src"{{h5Url}}" bindmessage"handleGetMessage"></web-view>H5.JSdata: { h5Url:https://xxx.com/login 要跳转的H5页面},H5回来的回调方法handleG…...

设计模式-单一职责原则

基本介绍 对类来说的&#xff0c;即一个类应该只负责一项职责。如类A负责两个不同的职责&#xff0c;职责1&#xff0c;职责2.当职责1需求变更而改变A时&#xff0c;可能造成职责2执行错误&#xff0c;所以需要将类A的粒度分解为A1&#xff0c;A2 应用实例 方案1 public cl…...

vue和nunjucks的变量插值的形式{{}}冲突

Nunjucks 中修改配置 const nunjucks require(nunjucks);const template_old nunjucks.renderString(template_old: Hello, {{name}}!, { name: World }); console.log(template_old); // 配置 Nunjucks 环境 nunjucks.configure({tags: {variableStart: $(, // 设置变量起始…...

从虚拟到物理:电子系统原型设计的工程化策略与实战解析

1. 原型设计全景&#xff1a;从概念到实物的工程化思维 在电子系统设计领域&#xff0c;尤其是面对航空航天、汽车电子、通信设备这类高复杂、高可靠性要求的项目时&#xff0c;“原型”这个词的分量远超一个简单的模型。它不是一个可有可无的步骤&#xff0c;而是连接创意与产…...

从Matlab到示波器:手把手教你用Vivado和FPGA实现20kHz SPWM信号(附完整代码)

从Matlab到示波器&#xff1a;FPGA实现20kHz SPWM信号的工程实践指南 在电力电子和电机控制领域&#xff0c;SPWM&#xff08;正弦脉宽调制&#xff09;技术因其高效和精确的特性而广受青睐。本文将带领读者完成一个完整的FPGA实现SPWM信号的工程流程&#xff0c;从Matlab数据生…...

如何在PC上快速配置yuzu模拟器:完整游戏体验指南

如何在PC上快速配置yuzu模拟器&#xff1a;完整游戏体验指南 【免费下载链接】yuzu 任天堂 Switch 模拟器 项目地址: https://gitcode.com/GitHub_Trending/yu/yuzu 想在电脑上畅玩任天堂Switch游戏吗&#xff1f;yuzu模拟器是你的最佳选择&#xff01;作为目前最成熟的…...

iVentoy(增强版PXE服务器

链接&#xff1a;https://pan.quark.cn/s/d2ca56327274iVentoy是一个增强版的PXE服务器。你可以通过网络同时为多台机器启动和安装操作系统。软件的使用非常简单&#xff0c;无需复杂的配置。只需要直接将ISO文件放在指定的位置&#xff0c;然后在启动时&#xff0c;客户机可以…...

活动策划27年:一场手印启动,让我读懂“谨慎”二字

活动策划27年&#xff1a;一场手印启动&#xff0c;让我读懂“谨慎”二字做活动策划27年&#xff0c;千余场活动下来&#xff0c;我常跟团队说&#xff1a;“做活动&#xff0c;不怕累&#xff0c;就怕措手不及的意外。”每一场活动前&#xff0c;我都要反复推演流程&#xff0…...

AI编码助手重复犯错?4大策略构建可控的智能编程伙伴

1. 项目概述&#xff1a;当AI编码助手陷入“重复犯错”的怪圈最近和几个团队的技术负责人聊天&#xff0c;发现大家都有个共同的烦恼&#xff1a;项目里引入的AI编码助手&#xff08;或者叫AI编程副驾&#xff09;&#xff0c;用着用着就发现它好像“不长记性”。同一个项目里&…...

告别双系统!Win11下用WSL2直通NVIDIA显卡跑PyTorch,保姆级配置避坑指南

告别双系统&#xff01;Win11下用WSL2直通NVIDIA显卡跑PyTorch&#xff0c;保姆级配置避坑指南 在深度学习开发中&#xff0c;Linux环境往往能提供更高效的GPU计算体验&#xff0c;但日常办公和娱乐又离不开Windows的便利。传统解决方案是安装双系统&#xff0c;频繁重启切换不…...

AI产品技能库实战:将专家经验注入Claude Code,打造你的虚拟产品专家

1. 项目概述&#xff1a;当AI助手遇上产品经理的“武林秘籍”如果你是一名产品经理、创业者&#xff0c;或者任何需要与产品打交道的人&#xff0c;最近可能已经感受到了AI助手带来的效率革命。无论是用Claude、ChatGPT还是其他工具来辅助写文档、分析数据&#xff0c;它们都像…...

SpringBoot快速入门指南

Spring Boot 是一个基于 Spring 框架的“约定优于配置”的快速应用开发框架&#xff0c;旨在简化基于 Spring 的应用初始搭建和开发过程。它通过自动配置、起步依赖和嵌入式容器等特性&#xff0c;使开发者能够快速创建独立的、生产级别的 Spring 应用程序。 一、 核心特性与快…...

如何免费实现iOS设备虚拟定位?iFakeLocation跨平台实用指南

如何免费实现iOS设备虚拟定位&#xff1f;iFakeLocation跨平台实用指南 【免费下载链接】iFakeLocation Simulate locations on iOS devices on Windows, Mac and Ubuntu. 项目地址: https://gitcode.com/gh_mirrors/if/iFakeLocation 你是否曾经想过&#xff0c;在舒适…...