1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package art; 18 19 import java.util.ArrayList; 20 import java.util.Collections; 21 import java.util.List; 22 import java.util.regex.Matcher; 23 import java.util.regex.Pattern; 24 25 public class PrintThread { print(String[][] stack)26 public static void print(String[][] stack) { 27 System.out.println("---------"); 28 for (String[] stackElement : stack) { 29 for (String part : stackElement) { 30 System.out.print(' '); 31 System.out.print(part); 32 } 33 System.out.println(); 34 } 35 } 36 print(Thread t, int start, int max)37 public static void print(Thread t, int start, int max) { 38 print(getStackTrace(t, start, max)); 39 } 40 41 // We have to ignore some threads when printing all stack traces. These are threads that may or 42 // may not exist depending on the environment. 43 public final static String IGNORE_THREAD_NAME_REGEX = 44 "Binder:|RenderThread|hwuiTask|Jit thread pool worker|Instr:|JDWP|Profile Saver|main|" + 45 "queued-work-looper|InstrumentationConnectionThread|intel_svc_streamer_thread|" + 46 "ForkJoinPool|Metrics Background Reporting Thread"; 47 public final static Matcher IGNORE_THREADS = 48 Pattern.compile(IGNORE_THREAD_NAME_REGEX).matcher(""); 49 50 // We have to skip the stack of some threads when printing all stack traces. These are threads 51 // that may have a different call stack (e.g., when run as an app), or may be in a 52 // non-deterministic state. 53 public final static String CUT_STACK_THREAD_NAME_REGEX = "Daemon|main"; 54 public final static Matcher CUT_STACK_THREADS = 55 Pattern.compile(CUT_STACK_THREAD_NAME_REGEX).matcher(""); 56 printAll(Object[][] stacks)57 public static void printAll(Object[][] stacks) { 58 List<String> stringified = new ArrayList<String>(stacks.length); 59 60 for (Object[] stackInfo : stacks) { 61 Thread t = (Thread)stackInfo[0]; 62 String name = (t != null) ? t.getName() : "null"; 63 String stackSerialization; 64 if (CUT_STACK_THREADS.reset(name).find()) { 65 // Do not print daemon stacks, as they're non-deterministic. 66 stackSerialization = "<not printed>"; 67 } else if (IGNORE_THREADS.reset(name).find()) { 68 // Skip IGNORE_THREADS. 69 continue; 70 } else { 71 StringBuilder sb = new StringBuilder(); 72 for (String[] stackElement : (String[][])stackInfo[1]) { 73 for (String part : stackElement) { 74 sb.append(' '); 75 sb.append(part); 76 } 77 sb.append('\n'); 78 } 79 stackSerialization = sb.toString(); 80 } 81 stringified.add(name + "\n" + stackSerialization); 82 } 83 84 Collections.sort(stringified); 85 86 for (String s : stringified) { 87 System.out.println("---------"); 88 System.out.println(s); 89 } 90 } 91 getStackTrace(Thread thread, int start, int max)92 public static native String[][] getStackTrace(Thread thread, int start, int max); 93 } 94