大厂的OOM优化和监控方案(二)

简介: 大厂的OOM优化和监控方案(二)
  • 四、打开太多文件
  • 4.1 错误信息
  • 4.2 系统限制
  • 4.2 文件描述符优化
  • 4.3 文件描述符监控
  • 4.4 IO监控

四、打开太多文件

4.1 错误信息

E/art: ashmem_create_region failed for 'indirect ref table': Too many open files
Java.lang.OutOfMemoryError: Could not allocate JNI Env

这个问题跟系统、厂商关系比较大

4.2 系统限制

Android是基于Linux内核,/proc/pid/limits 描述着linux系统对每个进程的一些资源限制,

如下图是一台Android 6.0的设备,Max open files的限制是1024

微信图片_20220906140735.jpg

如果没有root权限,可以通过ulimit -n命令查看Max open files,结果是一样的

ulimit -n

微信图片_20220906140754.jpg

Linux 系统一切皆文件,进程每打开一个文件就会产生一个文件描述符fd(记录在/proc/pid/fd下面)

cd /proc/10654/fd

ls

微信图片_20220906140813.jpg

这些fd文件都是链接文件,通过 ls -l可以查看其对应的真实文件路径

微信图片_20220906140830.jpg

当fd的数目达到Max open files规定的数目,就会触发Too many open files的奔溃,这种奔溃在低端机上比较容易复现。

知道了文件描述符这玩意后,看看怎么优化~

4.2 文件描述符优化

对于打开文件数太多的问题,盲目优化其实无从下手,总体的方案是监控为主。

通过如下代码可以查看当前进程的fd信息

private fun dumpFd() {
        val fdNames = runCatching { File("/proc/self/fd").listFiles() }
            .getOrElse {
                return@getOrElse emptyArray()
            }
            ?.map { file ->
                runCatching { Os.readlink(file.path) }.getOrElse { "failed to read link ${file.path}" }
            }
            ?: emptyList()
        Log.d("TAG", "dumpFd: size=${fdNames.size},fdNames=$fdNames")
    }

4.3 文件描述符监控

监控策略:当fd数大于1000个,或者fd连续递增超过50个,就触发fd收集,将fd对应的文件路径上报到后台。

这里模拟一个bug,打开一个文件多次不关闭,通过dumpFd,可以看到很多重复的文件名,进而大致定位到问题。

微信图片_20220906140912.jpg

当怀疑某个文件有问题之后,我们还需要知道这个文件在哪创建,是谁创建的,这个就涉及到IO监控~

4.4 IO监控

4.4.1 监控内容

监控完整的IO操作,包括open、read、write、close

open :获取文件名、fd、文件大小、堆栈、线程

read/write :获取文件类型、读写次数、总大小,使用buffer大小、读写总耗时

close :打开文件总耗时、最大连续读写时间

4.4.2 Java监控方案:

以Android 6.0 源码为例,FileInputStream 的调用链如下

java : FileInputStream -> IoBridge.open -> Libcore.os.open ->  
 BlockGuardOs.open -> Posix.open

Libcore.java是一个不错的hook点

package libcore.io;
public final class Libcore {
    private Libcore() { }
    public static Os os = new BlockGuardOs(new Posix());
}

我们可以通过反射获取到这个Os变量,它是一个接口类型,里面定义了open、read、write、close方法,具体实现在BlockGuardOs里面。

// 反射获得静态变量
Class<?> clibcore = Class.forName("libcore.io.Libcore");
Field fos = clibcore.getDeclaredField("os");

通过动态代理的方式,在它所有IO方法前后加入插桩代码来统计IO信息

// 动态代理对象
Proxy.newProxyInstance(cPosix.getClassLoader(), getAllInterfaces(cPosix), this);
beforeInvoke(method, args, throwable);
result = method.invoke(mPosixOs, args);
afterInvoke(method, args, result);

此方案缺点如下:

  • 性能差,IO调用频繁,使用动态代理和Java的字符串操作,导致性能较差,无法达到线上使用标准
  • 无法监控Native代码,这个也是比较重要的
  • 兼容性差:需要根据Android 版本做适配,特别是Android P的非公开API限制

4.4.3 Native监控方案

Native Hook方案的核心从 libc.so 中的这几个函数中选定 Hook 的目标函数

int open(const char *pathname, int flags, mode_t mode);
ssize_t read(int fd, void *buf, size_t size);
ssize_t write(int fd, const void *buf, size_t size); write_cuk
int close(int fd);

我们需要选择一些有调用上面几个方法的 library,例如选择libjavacore.so、libopenjdkjvm.so、libopenjdkjvm.so,可以覆盖到所有的 Java 层的 I/O 调用。

不同版本的 Android 系统实现有所不同,在 Android 7.0 之后,我们还需要替换下面这三个方法。

open64
__read_chk
__write_chk

native hook 框架目前使用比较广泛的是爱奇艺的xhook ,以及它的改进版,字节跳动的bhook。

具体的native IO监控代码,可以参考 Matrix-IOCanary,内部使用的是xhook框架。

关于IO涉及到的知识非常多,后面有时间可以单独整理一篇文章。

接下来看看最后一种OOM类型~

相关文章
|
3月前
|
消息中间件 存储 Java
jvm性能调优实战 - 47超大数据量处理系统是如何OOM的
jvm性能调优实战 - 47超大数据量处理系统是如何OOM的
42 0
|
8月前
|
运维 监控 Java
内存溢出+CPU占用过高:问题排查+解决方案+复盘(超详细分析教程)
全网最全的内存溢出CPU占用过高排查文章,包含:问题出现现象+临时解决方案+复现问题+定位问题发生原因+优化代码+优化后进行压测,上线+复盘
1392 5
|
3月前
|
监控 数据可视化 Java
jvm性能调优实战 - 31从测试到上线_如何分析JVM运行状况及合理优化
jvm性能调优实战 - 31从测试到上线_如何分析JVM运行状况及合理优化
53 1
|
3月前
|
存储 Java 数据库
jvm性能调优 - 06线上应用部署JVM实战_堆内存预估与设置
jvm性能调优 - 06线上应用部署JVM实战_堆内存预估与设置
61 0
|
28天前
|
SQL 运维 NoSQL
【Redis 故障排查】「连接失败问题排查和解决」带你总体分析CPU及内存的使用率高问题排查指南及方案
【Redis 故障排查】「连接失败问题排查和解决」带你总体分析CPU及内存的使用率高问题排查指南及方案
33 0
|
9月前
|
Web App开发 Java Linux
【性能优化】使用Perfetto定位应用启动性能的瓶颈
本篇文章将会结合我个人对Perfetto的实际使用经历,讲解车载应用的启动时间是如何测量得到的,测量出启动时间后,我们又该如何找出其中的性能瓶颈。
848 1
【性能优化】使用Perfetto定位应用启动性能的瓶颈
|
SQL 缓存 监控
监控指标解读和JVM 分析&调优
监控指标解读和JVM 分析&调优
监控指标解读和JVM 分析&调优
|
存储 运维 Java
【JVM性能优化】服务发生OOM故障定位方案
【JVM性能优化】服务发生OOM故障定位方案
261 0
【JVM性能优化】服务发生OOM故障定位方案
|
存储 JSON 监控
大厂的OOM优化和监控方案(三)
大厂的OOM优化和监控方案(三)
大厂的OOM优化和监控方案(三)
|
监控 JavaScript Java
大厂的OOM优化和监控方案(一)
大厂的OOM优化和监控方案(一)
大厂的OOM优化和监控方案(一)