In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-24 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article introduces the relevant knowledge of "what is the information collection process of Android ANR". In the operation of actual cases, many people will encounter such a dilemma. Next, let the editor lead you to learn how to deal with these situations. I hope you can read it carefully and be able to achieve something!
one。 ANR scene
No matter whether it is the four major components or processes, whenever ANR occurs, the AMS.appNotResponding () method will eventually be called. Let's start with this method.
The following scenarios trigger the call to the AMS.appNotResponding method:
Service Timeout: for example, the front desk service is not completed within 20 seconds.
BroadcastQueue Timeout: for example, the foreground broadcast is not completed within 10 seconds.
InputDispatching Timeout: enter event distribution timeout 5s, including keystrokes and touch events.
two。 AppNotResponding processing flow
1. AMS.appNotResponding
Final void appNotResponding (ProcessRecord app, ActivityRecord activity, ActivityRecord parent, boolean aboveSystem, final String annotation) {. UpdateCpuStatsNow (); / / the first update of cpu statistics synchronized (this) {/ / PowerManager.reboot () will block for a long time, so ignore the ANR if (mShuttingDown) {return;} else if (app.notResponding) {return;} else if (app.crashing) {return at shutdown } / / record ANR to EventLog EventLog.writeEvent (EventLogTags.AM_ANR, app.userId, app.pid, app.processName, app.info.flags, annotation); / / add the current process to firstPids firstPids.add (app.pid); int parentPid = app.pid / / add the system_server process to firstPids if (MY_PID! = app.pid & & MY_PID! = parentPid) firstPids.add (MY_PID); for (int I = mLruProcesses.size ()-1; I > = 0; iMel -) {ProcessRecord r = mLruProcesses.get (I); if (r! = null & & r.thread! = null) {int pid = r.pid If (pid > 0 & & pid! = app.pid & & pid! = parentPid & & pid! = MY_PID) {if (r.persistent) {firstPids.add (pid); / / add the persistent process to firstPids} else {lastPids.put (pid, Boolean.TRUE) / / add other processes to lastPids}} / / record ANR output to main log StringBuilder info = new StringBuilder (); info.setLength (0); info.append ("ANR in") .append (app.processName) If (activity! = null & & activity.shortComponentName! = null) {info.append ("(") .append (activity.shortComponentName) .append (")");} info.append ("\ n"); info.append ("PID:") .append (app.pid) .append ("\ n"); if (annotation! = null) {info.append ("Reason:") .append (annotation) .append ("\ n") } if (parent! = null & & parent! = activity) {info.append ("Parent:") .append (parent.shortComponentName) .append ("\ n");} / / create CPU tracker object final ProcessCpuTracker processCpuTracker = new ProcessCpuTracker (true); / / output traces information [see section 2] File tracesFile = dumpStackTraces (true, firstPids, processCpuTracker, lastPids, NATIVE_STACKS_OF_INTEREST) UpdateCpuStatsNow (); / / second update of cpu statistics / / record the current CPU usage of each process synchronized (mProcessCpuTracker) {cpuInfo = mProcessCpuTracker.printCurrentState (anrTime);} / / record the current CPU load info.append (processCpuTracker.printCurrentLoad ()); info.append (cpuInfo) / record the Cpu usage info.append (processCpuTracker.printCurrentState (anrTime)) since anr time; / / output the reason of the current ANR, as well as CPU usage and load information Slog.e (TAG, info.toString ()) / / Save traces file and CPU usage information to dropbox, that is, data/system/dropbox directory addErrorToDropBox ("anr", app, app.processName, activity, parent, annotation, cpuInfo, tracesFile, null) In the case of synchronized (this) {. / / background ANR, directly kill if (! showBackground & &! app.isInterestingToUserLocked () & & app.pid! = MY_PID) {app.kill ("bg anr", true); return } / / set the ANR status of app, and report receiver makeAppNotRespondingLocked (app, activity! = null? Activity.shortComponentName: null, annotation! = null? "ANR" + annotation: "ANR", info.toString (); / / rename the trace file String tracesPath = SystemProperties.get ("dalvik.vm.stack-trace-file", null); if (tracesPath! = null & & tracesPath.length ()! = 0) {/ / traceRenameFile = "/ data/anr/traces.txt" File traceRenameFile = new File (tracesPath); String newTracesPath Int lpos = tracesPath.lastIndexOf ("."); if (- 1! = lpos) / / New traces file = / data/anr/traces_ process name _ current date .txt newTracesPath = tracesPath.substring (0, lpos) + "_" + app.processName + "_" + mTraceDateFormat.format (new Date ()) + tracesPath.substring (lpos) Else newTracesPath = tracesPath + "_" + app.processName; traceRenameFile.renameTo (new File (newTracesPath));} / / pop-up ANR dialog Message msg = Message.obtain (); HashMap map = new HashMap (); msg.what = SHOW_NOT_RESPONDING_MSG; msg.obj = map Msg.arg1 = aboveSystem? 1: 0; map.put ("app", app); if (activity! = null) {map.put ("activity", activity);} / / send a message mUiHandler.sendMessage (msg) with SHOW_NOT_RESPONDING_MSG content to UI thread;}}
When ANR occurs, it is executed sequentially:
Output ANR Reason information to EventLog. That is to say, the closest point in time that ANR triggers is the am_anr information output from EventLog.
It is time-consuming to collect and output traces information for each thread in the list of important processes. [see section 2]
Output the current CPU usage and CPU load of each process
Save the traces file and CPU usage information to dropbox, the data/system/dropbox directory
According to the process type, to decide whether to kill directly in the background or to inform the user by popping the box.
ANR outputs traces information for important processes, which include:
FirstPids queue: the first is the ANR process, the second is system_server, and the rest are all persistent processes
Native queue: refers to the mediaserver,sdcard and surfaceflinger processes in the / system/bin/ directory
LastPids queue: refers to all processes in the mLruProcesses that do not belong to firstPids.
2. AMS.dumpStackTraces
Public static File dumpStackTraces (boolean clearTraces, ArrayList firstPids, ProcessCpuTracker processCpuTracker, SparseArray lastPids, String [] nativeProcs) {/ / defaults to data/anr/traces.txt String tracesPath = SystemProperties.get ("dalvik.vm.stack-trace-file", null); if (tracesPath = = null | | tracesPath.length () = 0) {return null;} File tracesFile = new File (tracesPath) Try {/ / when clearTraces, delete the existing traces file if (clearTraces & & tracesFile.exists ()) tracesFile.delete (); / / create the traces file tracesFile.createNewFile (); FileUtils.setPermissions (tracesFile.getPath (), 0666,-1,-1);} catch (IOException e) {return null } / / output trace content [see section 3] dumpStackTraces (tracesPath, firstPids, processCpuTracker, lastPids, nativeProcs); return tracesFile;}
This ensures that the contents of the data/anr/traces.txt file are entirely new, not appended.
3. AMS.dumpStackTraces
Private static void dumpStackTraces (String tracesPath, ArrayList firstPids, ProcessCpuTracker processCpuTracker, SparseArray lastPids, String [] nativeProcs) {FileObserver observer = new FileObserver (tracesPath, FileObserver.CLOSE_WRITE) {@ Override public synchronized void onEvent (int event, String path) {notify ();}}; try {observer.startWatching () / / first, get the stacks if (firstPids! = null) {try {int num = firstPids.size (); for (int I = 0; I) of the most important process
< num; i++) { synchronized (observer) { //向目标进程发送signal来输出traces Process.sendSignal(firstPids.get(i), Process.SIGNAL_QUIT); observer.wait(200); //等待直到写关闭,或者200ms超时 } } } catch (InterruptedException e) { Slog.wtf(TAG, e); } } //下一步,获取native进程的stacks if (nativeProcs != null) { int[] pids = Process.getPidsForCommands(nativeProcs); if (pids != null) { for (int pid : pids) { //输出native进程的trace【见小节4】 Debug.dumpNativeBacktraceToFile(pid, tracesPath); } } } if (processCpuTracker != null) { processCpuTracker.init(); System.gc(); processCpuTracker.update(); synchronized (processCpuTracker) { processCpuTracker.wait(500); //等待500ms } //测量CPU使用情况 processCpuTracker.update(); //从lastPids中选取CPU使用率 top 5的进程,输出这些进程的stacks final int N = processCpuTracker.countWorkingStats(); int numProcs = 0; for (int i=0; iGetStringCritical(fileName, 0); String8 fileName8; if (str) { fileName8 = String8(reinterpret_cast(str), env->GetStringLength (fileName); env- > ReleaseStringCritical (fileName, str);} / / Open / data/anr/traces.txt int fd = open (fileName8.string (), O_CREAT | O_WRONLY | O_NOFOLLOW, 0666); / *-rw-rw-rw- * /. If (lseek (fd, 0, SEEK_END)
< 0) { fprintf(stderr, "lseek: %s\n", strerror(errno)); } else { //【见小节5】 dump_backtrace_to_file(pid, fd); } close(fd);} 5. dump_backtrace_to_file [->Debugger.c]
Int dump_backtrace_to_file (pid_t tid, int fd) {return dump_backtrace_to_file_timeout (tid, fd, 0);} int dump_backtrace_to_file_timeout (pid_t tid, int fd, int timeout_secs) {/ / send dump backtrace request to the server via socket int sock_fd = make_dump_request (DEBUGGER_ACTION_DUMP_BACKTRACE, tid, timeout_secs); if (sock_fd)
< 0) { return -1; } int result = 0; char buffer[1024]; ssize_t n; //阻塞等待,从sock_fd中读取到服务端发送过来的数据,并写入buffer while ((n = TEMP_FAILURE_RETRY(read(sock_fd, buffer, sizeof(buffer)))) >0) {/ / then export the buffer data to the traces.txt file if (TEMP_FAILURE_RETRY (write (fd, buffer, n))! = n) {result =-1; break;}} close (sock_fd); return result;}
As you can see, this process is mainly by sending the command DEBUGGER_ACTION_DUMP_BACKTRACE to the debuggerd daemon, which debuggerd receives, and calls dump_backtrace () in the child process to output backtrace.
three。 Summary
When ANR is triggered, the system outputs key information: (this is more time-consuming and may have 10 seconds)
1. Output the am_anr information to EventLog. (see EventLog at the starting point of ANR)
two。 Get important process trace information and save it to / data/anr/traces.txt; (the old file will be deleted first)
Traces of the Java process
Traces of the Native process
3.ANR reason and CPU usage information, output to main log
4. Then save the CPU usage and process trace file information to / data/system/dropbox
The output of process Trace is the most core link in the whole process. Java and Native processes adopt different strategies, as follows:
Process type trace command description Javakill-3 [pid] does not apply to Native processes Nativedebuggerd-b [pid] also applies to Java processes
Note: the kill-3 command needs the support of the virtual machine, so you can't output the Native process traces. Debuggerd-b [pid] can also be used in Java processes, but it is far less informative than kill-3. In short, the most important ANR information is dropbox information, such as system_server_anr.
Important nodes:
Process name: cat / proc/ [pid] / cmdline
Thread name: cat / proc/ [tid] / comm
Kernel stack: cat / proc/ [tid] / stack
Native stack: parsing / proc/ [pid] / maps
This is the end of the content of "what is the information gathering process of Android ANR". Thank you for your reading. If you want to know more about the industry, you can follow the website, the editor will output more high-quality practical articles for you!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.