xCrash 是爱奇艺团队开源的一款崩溃日志收集库,可以收集 java crash、native crash 和 ANR 日志
日志格式为专用格式,内容还算丰富:机器信息、崩溃线程和其他线程的方法栈、logcat、打开的 fd 等等 ...
默认配置为:
捕获 Java Crash 用的是 DefaultUncaughtExceptionHandler,相关的基础知识参考 Uncaught Exception Handling
class JavaCrashHandler implements UncaughtExceptionHandler {
@Override
public void uncaughtException(Thread thread, Throwable throwable) {
if (defaultHandler != null) {
Thread.setDefaultUncaughtExceptionHandler(defaultHandler);
}
try {
handleException(thread, throwable);
} catch (Exception e) {
XCrash.getLogger().e(Util.TAG, "JavaCrashHandler handleException failed", e);
}
// 可以选择重新抛出给上一个 handler,或者杀死 app
if (this.rethrow) {
if (defaultHandler != null) {
defaultHandler.uncaughtException(thread, throwable);
}
} else {
ActivityMonitor.getInstance().finishAllActivities();
Process.killProcess(this.pid);
System.exit(10);
}
}
// 收集各种各样的信息,写入到日志文件
private void handleException(Thread thread, Throwable throwable) {
Date crashTime = new Date();
//notify the java crash
NativeHandler.getInstance().notifyJavaCrashed();
AnrHandler.getInstance().notifyJavaCrashed();
//create log file
File logFile = null;
try {
String logPath = String.format(Locale.US, "%s/%s_%020d_%s__%s%s", logDir, Util.logPrefix, startTime.getTime() * 1000, appVersion, processName, Util.javaLogSuffix);
logFile = FileManager.getInstance().createLogFile(logPath);
} catch (Exception e) {
XCrash.getLogger().e(Util.TAG, "JavaCrashHandler createLogFile failed", e);
}
//get emergency
String emergency = null;
try {
emergency = getEmergency(crashTime, thread, throwable);
} catch (Exception e) {
XCrash.getLogger().e(Util.TAG, "JavaCrashHandler getEmergency failed", e);
}
//write info to log file
if (logFile != null) {
RandomAccessFile raf = null;
try {
raf = new RandomAccessFile(logFile, "rws");
//write emergency info
if (emergency != null) {
raf.write(emergency.getBytes("UTF-8"));
}
//If we wrote the emergency info successfully, we don't need to return it from callback again.
emergency = null;
//write logcat
if (logcatMainLines > 0 || logcatSystemLines > 0 || logcatEventsLines > 0) {
raf.write(Util.getLogcat(logcatMainLines, logcatSystemLines, logcatEventsLines).getBytes("UTF-8"));
}
//write fds
if (dumpFds) {
raf.write(Util.getFds().getBytes("UTF-8"));
}
//write network info
if (dumpNetworkInfo) {
raf.write(Util.getNetworkInfo().getBytes("UTF-8"));
}
//write memory info
raf.write(Util.getMemoryInfo().getBytes("UTF-8"));
//write background / foreground
raf.write(("foreground:\\\\n" + (ActivityMonitor.getInstance().isApplicationForeground() ? "yes" : "no") + "\\\\n\\\\n").getBytes("UTF-8"));
//write other threads info
if (dumpAllThreads) {
raf.write(getOtherThreadsInfo(thread).getBytes("UTF-8"));
}
} catch (Exception e) {
XCrash.getLogger().e(Util.TAG, "JavaCrashHandler write log file failed", e);
} finally {
if (raf != null) {
try {
raf.close();
} catch (Exception ignored) {
}
}
}
}
//callback
if (callback != null) {
try {
callback.onCrash(logFile == null ? null : logFile.getAbsolutePath(), emergency);
} catch (Exception ignored) {
}
}
}
}
private String getEmergency(Date crashTime, Thread thread, Throwable throwable) {
//stack stace
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
throwable.printStackTrace(pw);
String stacktrace = sw.toString();
return Util.getLogHeader(startTime, crashTime, Util.javaCrashType, appId, appVersion)
+ "pid: " + pid + ", tid: " + Process.myTid() + ", name: " + thread.getName() + " >>> " + processName + " <<<\\\\n"
+ "\\\\n"
+ "java stacktrace:\\\\n"
+ stacktrace
+ "\\\\n"
+ getBuildId(stacktrace);
}
static String getLogHeader(Date startTime, Date crashTime, String crashType, String appId, String appVersion) {
DateFormat timeFormatter = new SimpleDateFormat(Util.timeFormatterStr, Locale.US);
return Util.sepHead + "\\\\n"
+ "Tombstone maker: '" + Version.fullVersion + "'\\\\n"
+ "Crash type: '" + crashType + "'\\\\n"
+ "Start time: '" + timeFormatter.format(startTime) + "'\\\\n"
+ "Crash time: '" + timeFormatter.format(crashTime) + "'\\\\n"
+ "App ID: '" + appId + "'\\\\n"
+ "App version: '" + appVersion + "'\\\\n"
+ "Rooted: '" + (Util.isRoot() ? "Yes" : "No") + "'\\\\n"
+ "API level: '" + Build.VERSION.SDK_INT + "'\\\\n"
+ "OS version: '" + Build.VERSION.RELEASE + "'\\\\n"
+ "ABI list: '" + Util.getAbiList() + "'\\\\n"
+ "Manufacturer: '" + Build.MANUFACTURER + "'\\\\n"
+ "Brand: '" + Build.BRAND + "'\\\\n"
+ "Model: '" + Util.getMobileModel() + "'\\\\n"
+ "Build fingerprint: '" + Build.FINGERPRINT + "'\\\\n";
}
private String getBuildId(String stktrace) {
String buildId = "";
List<String> libPathList = new ArrayList<String>();
if (stktrace.contains("UnsatisfiedLinkError")) {
String libInfo = null;
String[] tempLibPathStr;
tempLibPathStr = stktrace.split("\\\\""); // " is the delimiter
for (String libPathStr : tempLibPathStr) {
if (libPathStr.isEmpty() || !libPathStr.endsWith(".so")) continue;
libPathList.add(libPathStr);
String libName = libPathStr.substring(libPathStr.lastIndexOf('/') + 1);
libPathList.add(XCrash.nativeLibDir + "/" + libName);
libPathList.add("/vendor/lib/" + libName);
libPathList.add("/vendor/lib64/" + libName);
libPathList.add("/system/lib/" + libName);
libPathList.add("/system/lib64/" + libName);
libInfo = getLibInfo(libPathList);
}
buildId = "build id:"
+ "\\\\n"
+ libInfo
+ "\\\\n";
}
return buildId;
}
输出的日志内容如下:
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Tombstone maker: 'xCrash 2.4.6' // xCrash 把日志叫做 tombstone,这里指的是生成 tombstone 的 xCrash 的版本
Crash type: 'java' // 指明 crash 类型,此日志包含的是 java crash(此外还有 native crash 和 ANR)
Start time: '2019-10-12T03:23:19.580+0800' // 初始化 xCrash 的时间,也就是调用 XCrash.init 的时间
Crash time: '2019-10-12T03:23:25.533+0800' // 发生崩溃的时间
App ID: 'xcrash.sample' // 发生崩溃的 APP 的包名
App version: '1.2.3-beta456-patch789' // APP version name
Rooted: 'No'
API level: '29'
OS version: '10'
ABI list: 'arm64-v8a,armeabi-v7a,armeabi'
Manufacturer: 'Google'
Brand: 'google'
Model: 'Pixel'
Build fingerprint: 'google/sailfish/sailfish:10/QP1A.190711.020/5800535:user/release-keys'
pid: 21356, tid: 21356, name: main >>> xcrash.sample <<<
java stacktrace: // 崩溃线程的调用栈
java.lang.IllegalStateException: Could not execute method for android:onClick
at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:402)
at android.view.View.performClick(View.java:7140)
at android.view.View.performClickInternal(View.java:7117)
at android.view.View.access$3500(View.java:801)
at android.view.View$PerformClick.run(View.java:27351)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at androidx.appcompat.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:397)
... 11 more
Caused by: java.lang.RuntimeException: test java exception
at xcrash.XCrash.testJavaCrash(XCrash.java:847)
at xcrash.sample.MainActivity.testJavaCrashInMainThread_onClick(MainActivity.java:67)
... 13 more
static String getLogcat(int logcatMainLines, int logcatSystemLines, int logcatEventsLines) {
int pid = android.os.Process.myPid();
StringBuilder sb = new StringBuilder();
sb.append("logcat:\\\\n");
if (logcatMainLines > 0) {
getLogcatByBufferName(pid, sb, "main", logcatMainLines, 'D');
}
if (logcatSystemLines > 0) {
getLogcatByBufferName(pid, sb, "system", logcatSystemLines, 'W');
}
if (logcatEventsLines > 0) {
getLogcatByBufferName(pid, sb, "events", logcatSystemLines, 'I');
}
sb.append("\\\\n");
return sb.toString();
}
private static void getLogcatByBufferName(int pid, StringBuilder sb, String bufferName, int lines, char priority) {
boolean withPid = (android.os.Build.VERSION.SDK_INT >= 24);
String pidString = Integer.toString(pid);
String pidLabel = " " + pidString + " ";
//command for ProcessBuilder
List<String> command = new ArrayList<String>();
command.add("/system/bin/logcat");
command.add("-b");
command.add(bufferName);
command.add("-d");
command.add("-v");
command.add("threadtime");
command.add("-t");
command.add(Integer.toString(withPid ? lines : (int) (lines * 1.2)));
if (withPid) {
command.add("--pid");
command.add(pidString);
}
command.add("*:" + priority);
//append the command line
Object[] commandArray = command.toArray();
sb.append("--------- tail end of log ").append(bufferName);
sb.append(" (").append(android.text.TextUtils.join(" ", commandArray)).append(")\\\\n");
//append logs
BufferedReader br = null;
String line;
try {
Process process = new ProcessBuilder().command(command).start();
br = new BufferedReader(new InputStreamReader(process.getInputStream()));
while ((line = br.readLine()) != null) {
if (withPid || line.contains(pidLabel)) {
sb.append(line).append("\\\\n");
}
}
} catch (Exception e) {
XCrash.getLogger().w(Util.TAG, "Util run logcat command failed", e);
} finally {
if (br != null) {
try {
br.close();
} catch (IOException ignored) {
}
}
}
}
其实就是调用 logcat 命令获取崩溃时的 main、system 和 events 三个 buffer 的日志,如:/system/bin/logcat -b main -d -v threadtime -t 200 --pid 21356 *:D
输出如下:
logcat:
--------- tail end of log main (/system/bin/logcat -b main -d -v threadtime -t 200 --pid 21356 *:D)
10-12 03:23:19.356 21356 21356 I xcrash.sample: Late-enabling -Xcheck:jni
10-12 03:23:19.398 21356 21356 E xcrash.sample: Unknown bits set in runtime_flags: 0x8000
10-12 03:23:19.571 21356 21356 D xcrash_sample: xCrash SDK init: start
10-12 03:23:19.586 21356 21356 D xcrash_sample: xCrash SDK init: end
10-12 03:23:19.757 21356 21356 W xcrash.sample: Accessing hidden method Landroid/view/View;->computeFitSystemWindows(Landroid/graphics/Rect;Landroid/graphics/Rect;)Z (greylist, reflection, allowed)
10-12 03:23:19.758 21356 21356 W xcrash.sample: Accessing hidden method Landroid/view/ViewGroup;->makeOptionalFitsSystemWindows()V (greylist, reflection, allowed)
10-12 03:23:19.829 21356 21356 I WebViewFactory: Loading com.google.android.webview version 77.0.3865.92 (code 386509238)
10-12 03:23:19.874 21356 21356 I cr_LibraryLoader: Time to load native libraries: 4 ms (timestamps 1922-1926)
10-12 03:23:19.920 21356 21356 I chromium: [INFO:library_loader_hooks.cc(51)] Chromium logging enabled: level = 0, default verbosity = 0
10-12 03:23:19.921 21356 21356 I cr_LibraryLoader: Expected native library version number "77.0.3865.92", actual native library version number "77.0.3865.92"
10-12 03:23:19.926 21356 21402 W cr_ChildProcLH: Create a new ChildConnectionAllocator with package name = com.google.android.webview, sandboxed = true
10-12 03:23:19.930 21356 21402 W xcrash.sample: Accessing hidden method Landroid/content/Context;->bindServiceAsUser(Landroid/content/Intent;Landroid/content/ServiceConnection;ILandroid/os/Handler;Landroid/os/UserHandle;)Z (greylist, reflection, allowed)
10-12 03:23:19.934 21356 21356 I cr_BrowserStartup: Initializing chromium process, singleProcess=false
10-12 03:23:19.979 21356 21430 W chromium: [WARNING:dns_config_service_posix.cc(339)] Failed to read DnsConfig.
10-12 03:23:20.031 21356 21356 W xcrash.sample: Accessing hidden method Landroid/view/textclassifier/logging/SmartSelectionEventTracker;-><init>(Landroid/content/Context;I)V (greylist, reflection, allowed)
10-12 03:23:20.031 21356 21356 W xcrash.sample: Accessing hidden method Landroid/view/textclassifier/logging/SmartSelectionEventTracker;->logEvent(Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;)V (greylist, reflection, allowed)
10-12 03:23:20.032 21356 21356 W xcrash.sample: Accessing hidden method Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;->selectionStarted(I)Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent; (greylist, reflection, allowed)
10-12 03:23:20.032 21356 21356 W xcrash.sample: Accessing hidden method Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;->selectionModified(II)Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent; (greylist, reflection, allowed)
10-12 03:23:20.032 21356 21356 W xcrash.sample: Accessing hidden method Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;->selectionModified(IILandroid/view/textclassifier/TextClassification;)Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent; (greylist, reflection, allowed)
10-12 03:23:20.032 21356 21356 W xcrash.sample: Accessing hidden method Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;->selectionModified(IILandroid/view/textclassifier/TextSelection;)Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent; (greylist, reflection, allowed)
10-12 03:23:20.032 21356 21356 W xcrash.sample: Accessing hidden method Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;->selectionAction(III)Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent; (greylist, reflection, allowed)
10-12 03:23:20.032 21356 21356 W xcrash.sample: Accessing hidden method Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent;->selectionAction(IIILandroid/view/textclassifier/TextClassification;)Landroid/view/textclassifier/logging/SmartSelectionEventTracker$SelectionEvent; (greylist, reflection, allowed)
10-12 03:23:20.143 21356 21395 I Adreno : QUALCOMM build : 4a00b69, I4e7e888065
10-12 03:23:20.143 21356 21395 I Adreno : Build Date : 04/09/19
10-12 03:23:20.143 21356 21395 I Adreno : OpenGL ES Shader Compiler Version: EV031.26.06.00
10-12 03:23:20.143 21356 21395 I Adreno : Local Branch : mybranche95ae4c8-d77f-f18d-a9ef-1458d0b52ae8
10-12 03:23:20.143 21356 21395 I Adreno : Remote Branch : quic/gfx-adreno.lnx.1.0
10-12 03:23:20.143 21356 21395 I Adreno : Remote Branch : NONE
10-12 03:23:20.143 21356 21395 I Adreno : Reconstruct Branch : NOTHING
10-12 03:23:20.143 21356 21395 I Adreno : Build Config : S L 8.0.5 AArch64
10-12 03:23:20.146 21356 21395 I Adreno : PFP: 0x005ff110, ME: 0x005ff066
10-12 03:23:20.198 21356 21395 W Gralloc3: mapper 3.x is not supported
10-12 03:23:25.531 21356 21356 D AndroidRuntime: Shutting down VM
--------- tail end of log system (/system/bin/logcat -b system -d -v threadtime -t 50 --pid 21356 *:W)
--------- tail end of log events (/system/bin/logcat -b events -d -v threadtime -t 50 --pid 21356 *:I)
10-12 03:23:20.046 21356 21356 I am_on_create_called: [0,xcrash.sample.MainActivity,performCreate]
10-12 03:23:20.053 21356 21356 I am_on_start_called: [0,xcrash.sample.MainActivity,handleStartActivity]
10-12 03:23:20.056 21356 21356 I am_on_resume_called: [0,xcrash.sample.MainActivity,RESUME_ACTIVITY]
10-12 03:23:20.083 21356 21356 I am_on_top_resumed_gained_called: [0,xcrash.sample.MainActivity,topStateChangedWhenResumed]
static String getFds() {
StringBuilder sb = new StringBuilder("open files:\\\\n");
try {
File dir = new File("/proc/self/fd");
File[] fds = dir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return TextUtils.isDigitsOnly(name);
}
});
int count = 0;
if (fds != null) {
for (File fd : fds) {
String path = null;
try {
if (Build.VERSION.SDK_INT >= 21) {
path = Os.readlink(fd.getAbsolutePath());
} else {
path = fd.getCanonicalPath();
}
} catch (Exception ignored) {
}
sb.append(" fd ").append(fd.getName()).append(": ")
.append(TextUtils.isEmpty(path) ? "???" : path.trim()).append('\\\\n');
count++;
if (count > 1024) {
break;
}
}
if (fds.length > 1024) {
sb.append(" ......\\\\n");
}
sb.append(" (number of FDs: ").append(fds.length).append(")\\\\n");
}
} catch (Exception ignored) {
}
sb.append('\\\\n');
return sb.toString();
}
打印已打开的 FD 及其路径,已打开的 FD 在目录 /proc/self/fd 下
open files:
fd 0: /dev/null
fd 1: /dev/null
fd 2: /dev/null
fd 3: /proc/21356/fd/3
fd 4: /proc/21356/fd/4
fd 5: /proc/21356/fd/5
fd 6: /dev/null
fd 7: /dev/null
fd 8: /dev/null
fd 9: /apex/com.android.runtime/javalib/core-oj.jar
fd 10: /apex/com.android.runtime/javalib/core-libart.jar
fd 11: /apex/com.android.runtime/javalib/okhttp.jar
fd 12: /apex/com.android.runtime/javalib/bouncycastle.jar
fd 13: /apex/com.android.runtime/javalib/apache-xml.jar
fd 14: /system/framework/framework.jar
fd 15: /system/framework/ext.jar
fd 16: /system/framework/telephony-common.jar
fd 17: /system/framework/voip-common.jar
fd 18: /system/framework/ims-common.jar
fd 19: /dev/null
fd 20: /dev/null
fd 21: /system/framework/android.test.base.jar
fd 22: /apex/com.android.conscrypt/javalib/conscrypt.jar
fd 23: /apex/com.android.media/javalib/updatable-media.jar
fd 24: /system/framework/framework-res.apk
fd 25: /system/product/overlay/GoogleConfigOverlay.apk
fd 26: /system/product/overlay/GoogleWebViewOverlay.apk
fd 27: /vendor/overlay/framework-res__auto_generated_rro_vendor.apk
fd 28: /system/product/overlay/PixelConfigOverlayCommon.apk
fd 29: /system/product/overlay/framework-res__auto_generated_rro_product.apk
fd 30: /dev/null
fd 31: /dev/binder
fd 32: /proc/21356/fd/32
fd 33: /proc/21356/fd/33
fd 34: /proc/21356/fd/34
fd 35: /proc/21356/fd/35
fd 36: /proc/21356/fd/36
fd 37: /data/app/xcrash.sample-WeCpVYjROKKgYtuzbHflHg==/base.apk
fd 38: /proc/21356/fd/38
fd 39: /proc/21356/fd/39
fd 40: /system/product/overlay/NavigationBarModeGestural/NavigationBarModeGesturalOverlay.apk
fd 41: /dev/null
fd 42: /dev/null
fd 43: /dev/null
fd 44: /dev/null
fd 45: /proc/21356/fd/45
fd 46: /proc/21356/fd/46
fd 47: /proc/21356/fd/47
fd 48: /proc/21356/fd/48
fd 49: /dev/ashmem
fd 50: /proc/21356/fd/50
fd 51: /proc/21356/fd/51
fd 52: /data/app/com.google.android.trichromelibrary_386509238-C5vGqz1rgNqceBgeyyw2Aw==/base.apk
fd 53: /proc/21356/fd/53
fd 54: /data/data/xcrash.sample/files/tombstones/tombstone_00001570821799580000_1.2.3-beta456-patch789__xcrash.sample.java.xcrash
fd 55: /data/app/com.google.android.webview-wtyVrSKc9Gzy-ujvyvTNjw==/base.apk
fd 56: /data/app/com.google.android.trichromelibrary_386509238-C5vGqz1rgNqceBgeyyw2Aw==/base.apk
fd 57: /data/data/xcrash.sample/app_webview/webview_data.lock
fd 58: /data/app/com.google.android.webview-wtyVrSKc9Gzy-ujvyvTNjw==/base.apk
fd 59: /system/product/overlay/NavigationBarModeGestural/NavigationBarModeGesturalOverlay.apk
fd 60: /proc/21356/fd/60
fd 61: /proc/21356/fd/61
fd 62: /data/app/com.google.android.trichromelibrary_386509238-C5vGqz1rgNqceBgeyyw2Aw==/base.apk
fd 63: /data/app/com.google.android.trichromelibrary_386509238-C5vGqz1rgNqceBgeyyw2Aw==/base.apk
fd 64: /data/app/com.google.android.webview-wtyVrSKc9Gzy-ujvyvTNjw==/base.apk
fd 65: /data/app/com.google.android.trichromelibrary_386509238-C5vGqz1rgNqceBgeyyw2Aw==/base.apk
fd 66: /dev/urandom
fd 67: /proc/21356/fd/67
fd 68: /proc/21356/fd/68
fd 69: /data/app/com.google.android.webview-wtyVrSKc9Gzy-ujvyvTNjw==/base.apk
fd 70: /proc/21356/fd/70
fd 71: /proc/21356/fd/71
fd 72: /data/app/com.google.android.webview-wtyVrSKc9Gzy-ujvyvTNjw==/base.apk
fd 73: /data/app/com.google.android.webview-wtyVrSKc9Gzy-ujvyvTNjw==/base.apk
fd 74: /proc/21356/fd/74
fd 75: /proc/21356/fd/75
fd 76: /proc/21356/fd/76
fd 77: /proc/21356/fd/77
fd 78: /proc/21356/fd/78
fd 79: /proc/21356/fd/79
fd 80: /proc/21356/fd/80
fd 81: /proc/21356/fd/81
fd 82: /proc/21356/fd/82
fd 83: /proc/21356/fd/83
fd 84: /proc/21356/fd/84
fd 85: /proc/21356/fd/85
fd 86: /proc/21356/fd/86
fd 87: /proc/21356/fd/87
fd 88: /proc/21356/fd/88
fd 89: /proc/21356/fd/89
fd 90: /proc/21356/fd/90
fd 91: /dev/ashmem
fd 92: /dev/ashmem
fd 93: /dev/ashmem
fd 94: /data/data/xcrash.sample/app_webview/Web Data
fd 95: /proc/21356/fd/95
fd 96: /proc/21356/fd/96
fd 97: /dev/ashmem
fd 98: /dev/ion
fd 99: /proc/21356/fd/99
fd 100: /proc/21356/fd/100
fd 101: /proc/21356/fd/101
fd 102: /dev/ashmem
fd 103: /dev/kgsl-3d0
fd 104: /dev/ion
fd 105: /dev/hwbinder
fd 106: /proc/21356/fd/106
fd 107: /proc/21356/fd/107
fd 110: /proc/21356/fd/110
fd 111: /proc/21356/fd/111
fd 113: /proc/21356/fd/113
fd 114: /proc/21356/fd/114
fd 115: /proc/21356/fd/115
fd 116: /proc/21356/fd/116
fd 117: /proc/21356/fd/117
(number of FDs: 115)
输出如下:
System Summary (From: /proc/meminfo)
MemTotal: 3855796 kB
MemFree: 90124 kB
MemAvailable: 1452636 kB
Buffers: 77420 kB
Cached: 1461900 kB
SwapCached: 10232 kB
Active: 1771504 kB
Inactive: 1014432 kB
Active(anon): 1046604 kB
Inactive(anon): 368348 kB
Active(file): 724900 kB
Inactive(file): 646084 kB
Unevictable: 151672 kB
Mlocked: 151672 kB
SwapTotal: 524284 kB
SwapFree: 271320 kB
Dirty: 136 kB
Writeback: 0 kB
AnonPages: 1391280 kB
Mapped: 620988 kB
Shmem: 16660 kB
Slab: 231556 kB
SReclaimable: 92700 kB
SUnreclaim: 138856 kB
KernelStack: 44448 kB
PageTables: 57544 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
WritebackTmp: 0 kB
CommitLimit: 2452180 kB
Committed_AS: 67847232 kB
VmallocTotal: 258998208 kB
VmallocUsed: 223632 kB
VmallocChunk: 258675172 kB