AndroidProcesses库是jared rummler大神的双一杰作http://jaredrummler.com/,该库简单来说是通过读取/proc/pid/目录下的文件,获取对应进程的信息,具体功能移动至 https://github.com/jaredrummler/AndroidProcesses最近我们项目中使用该库,线上收集到相关的崩溃信息如下(精简过后的backtrace):
Caused by: java.lang.ArrayIndexOutOfBoundsException: length=1; index=1
at Stat.getComm(Stat.java:198)
at AndroidProcess.getProcessName(AndroidProcess.java:44)
at AndroidProcess.<init>(AndroidProcess.java:65)
at AndroidAppProcess.<init>(AndroidAppProcess.java:48)
经分析应该是某些异常的情况出现,导致/proc/pid/stat的文件内容格式错乱或没有内容,临时的解决方案如下(加强代码的异常逻辑处理):
@@ -195,7 +195,8 @@ public final class Stat extends ProcFile {
* executable is swapped out.
*/
public String getComm() {
- return fields[1].replace("(", "").replace(")", "");
+ return fields != null && fields.length > 1 && fields[1] != null ?
+ fields[1].replace("(", "").replace(")", "") : null;
}
同时在github上提了一个 issues
在分析代码的过程中,发现一个有趣的现象,似乎/proc/pid/stat获取不到进程名(android应用对应的是包名),
通过现象分析发现进程名最多是15个字符,立即怀疑stat的文件生成或更新时进程名应该是有裁段的逻辑处理,
经翻查linux内核代码找到相关的关健代码如下
static ssize_t comm_write(struct file *file, const char __user *buf,
size_t count, loff_t *offset)
{
struct inode *inode = file_inode(file);
struct task_struct *p;
char buffer[TASK_COMM_LEN]; // TASK_COMM_LEN = 16
const size_t maxlen = sizeof(buffer) - 1;
memset(buffer, 0, sizeof(buffer));
if (copy_from_user(buffer, buf, count > maxlen ? maxlen : count))
return -EFAULT;
p = get_proc_task(inode);
if (!p)
return -ESRCH;
if (same_thread_group(current, p))
set_task_comm(p, buffer);
else
count = -EINVAL;
put_task_struct(p);
return count;
}
TASK_COMM_LEN的定义在include/linux/sched.h
167:#define TASK_COMM_LEN 16
725: char comm[TASK_COMM_LEN];
注:TASK_COMM_LEN是16,占用一位为作字符串的结构符,故stat文件中的进程名只有15位了
在github了提了一个 issues