• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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.Arrays;
21 import java.util.Comparator;
22 import java.util.Collections;
23 import java.util.Iterator;
24 import java.util.List;
25 
26 public class Test925 {
run()27   public static void run() throws Exception {
28     doTest();
29   }
30 
doTest()31   private static void doTest() throws Exception {
32     Thread t1 = Thread.currentThread();
33     ThreadGroup curGroup = t1.getThreadGroup();
34 
35     ThreadGroup rootGroup = curGroup;
36     while (rootGroup.getParent() != null) {
37       rootGroup = rootGroup.getParent();
38     }
39 
40     ThreadGroup topGroups[] = getTopThreadGroups();
41     if (topGroups == null || topGroups.length != 1 || topGroups[0] != rootGroup) {
42       System.out.println(Arrays.toString(topGroups));
43       throw new RuntimeException("Unexpected topGroups");
44     }
45 
46     printThreadGroupInfo(curGroup);
47     printThreadGroupInfo(rootGroup);
48 
49     waitGroupChildren(rootGroup, 5 /* # daemons */, 30 /* timeout in seconds */);
50 
51     checkChildren(curGroup);
52   }
53 
printThreadGroupInfo(ThreadGroup tg)54   private static void printThreadGroupInfo(ThreadGroup tg) {
55     Object[] threadGroupInfo = getThreadGroupInfo(tg);
56     if (threadGroupInfo == null || threadGroupInfo.length != 4) {
57       System.out.println(Arrays.toString(threadGroupInfo));
58       throw new RuntimeException("threadGroupInfo length wrong");
59     }
60 
61     System.out.println(tg);
62     System.out.println("  " + threadGroupInfo[0]);  // Parent
63     System.out.println("  " + threadGroupInfo[1]);  // Name
64     System.out.println("  " + threadGroupInfo[2]);  // Priority
65     System.out.println("  " + threadGroupInfo[3]);  // Daemon
66   }
67 
checkChildren(ThreadGroup tg)68   private static void checkChildren(ThreadGroup tg) {
69     Object[] data = getThreadGroupChildren(tg);
70     Thread[] threads = (Thread[])data[0];
71     ThreadGroup[] groups = (ThreadGroup[])data[1];
72 
73     List<Thread> threadList = new ArrayList<>(Arrays.asList(threads));
74 
75     // Filter out JIT thread. It may or may not be there depending on configuration.
76     Iterator<Thread> it = threadList.iterator();
77     while (it.hasNext()) {
78       Thread t = it.next();
79       if (t.getName().startsWith("Jit thread pool worker")) {
80         it.remove();
81         break;
82       }
83     }
84 
85     Collections.sort(threadList, THREAD_COMP);
86 
87     Arrays.sort(groups, THREADGROUP_COMP);
88     System.out.println(tg.getName() + ":");
89     System.out.println("  " + threadList);
90     System.out.println("  " + Arrays.toString(groups));
91 
92     if (tg.getParent() != null) {
93       checkChildren(tg.getParent());
94     }
95   }
96 
waitGroupChildren(ThreadGroup tg, int expectedChildCount, int timeoutS)97   private static void waitGroupChildren(ThreadGroup tg, int expectedChildCount, int timeoutS)
98       throws Exception {
99     for (int i = 0; i <  timeoutS; i++) {
100       Object[] data = getThreadGroupChildren(tg);
101       Thread[] threads = (Thread[])data[0];
102       if (threads.length == expectedChildCount) {
103         return;
104       }
105       Thread.sleep(1000);
106     }
107 
108     Object[] data = getThreadGroupChildren(tg);
109     Thread[] threads = (Thread[])data[0];
110     System.out.println(Arrays.toString(threads));
111     throw new RuntimeException("Waited unsuccessfully for " + expectedChildCount + " children.");
112   }
113 
114   private final static Comparator<Thread> THREAD_COMP = new Comparator<Thread>() {
115     public int compare(Thread o1, Thread o2) {
116       return o1.getName().compareTo(o2.getName());
117     }
118   };
119 
120   private final static Comparator<ThreadGroup> THREADGROUP_COMP = new Comparator<ThreadGroup>() {
121     public int compare(ThreadGroup o1, ThreadGroup o2) {
122       return o1.getName().compareTo(o2.getName());
123     }
124   };
125 
getTopThreadGroups()126   private static native ThreadGroup[] getTopThreadGroups();
getThreadGroupInfo(ThreadGroup tg)127   private static native Object[] getThreadGroupInfo(ThreadGroup tg);
128   // Returns an array where element 0 is an array of threads and element 1 is an array of groups.
getThreadGroupChildren(ThreadGroup tg)129   private static native Object[] getThreadGroupChildren(ThreadGroup tg);
130 }
131