blob: cb77e25cb78faebca531bae629829a95694bb047 [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package art;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CountDownLatch;
public class Test925 {
public static void run() throws Exception {
doTest();
}
private static void doTest() throws Exception {
Thread t1 = Thread.currentThread();
ThreadGroup curGroup = t1.getThreadGroup();
ThreadGroup rootGroup = curGroup;
while (rootGroup.getParent() != null) {
rootGroup = rootGroup.getParent();
}
ThreadGroup topGroups[] = getTopThreadGroups();
if (topGroups == null || topGroups.length != 1 || topGroups[0] != rootGroup) {
System.out.println(Arrays.toString(topGroups));
throw new RuntimeException("Unexpected topGroups");
}
printThreadGroupInfo(curGroup);
printThreadGroupInfo(rootGroup);
waitGroupChildren(rootGroup, 5 /* # daemons */, 30 /* timeout in seconds */);
checkChildren(curGroup);
// Test custom groups
ThreadGroup testGroup = new CustomThreadGroup(curGroup, "TEST GROUP");
final CountDownLatch cdl = new CountDownLatch(1);
final CountDownLatch startup = new CountDownLatch(1);
Thread t2 = new Thread(testGroup, "Test Thread") {
public void run() {
startup.countDown();
try {
cdl.await();
} catch (Exception e) {}
}
};
t2.start();
startup.await();
printThreadGroupInfo(testGroup);
cdl.countDown();
t2.join();
}
private static final class CustomThreadGroup extends ThreadGroup {
public CustomThreadGroup(ThreadGroup parent, String name) {
super(parent, name);
}
}
private static void printThreadGroupInfo(ThreadGroup tg) {
Object[] threadGroupInfo = getThreadGroupInfo(tg);
if (threadGroupInfo == null || threadGroupInfo.length != 4) {
System.out.println(Arrays.toString(threadGroupInfo));
throw new RuntimeException("threadGroupInfo length wrong");
}
System.out.println(tg);
System.out.println(" " + threadGroupInfo[0]); // Parent
System.out.println(" " + threadGroupInfo[1]); // Name
System.out.println(" " + threadGroupInfo[2]); // Priority
System.out.println(" " + threadGroupInfo[3]); // Daemon
}
private static ArrayList<Thread> filteredThread(Thread[] threads) {
ArrayList<Thread> list = new ArrayList<>(Arrays.asList(threads));
// Filter out JIT and reporting thread. They may or may not be there depending on configuration.
Iterator<Thread> it = list.iterator();
while (it.hasNext()) {
Thread t = it.next();
if (t.getName().startsWith("Jit thread pool worker") ||
t.getName().startsWith("Metrics Background Reporting Thread")) {
it.remove();
}
}
return list;
}
private static void checkChildren(ThreadGroup tg) {
Object[] data = getThreadGroupChildren(tg);
Thread[] threads = (Thread[])data[0];
ThreadGroup[] groups = (ThreadGroup[])data[1];
List<Thread> threadList = filteredThread(threads);
Collections.sort(threadList, THREAD_COMP);
Arrays.sort(groups, THREADGROUP_COMP);
System.out.println(tg.getName() + ":");
System.out.println(" " + threadList);
System.out.println(" " + Arrays.toString(groups));
if (tg.getParent() != null) {
checkChildren(tg.getParent());
}
}
private static void waitGroupChildren(ThreadGroup tg, int expectedChildCount, int timeoutS)
throws Exception {
for (int i = 0; i < timeoutS; i++) {
Object[] data = getThreadGroupChildren(tg);
Thread[] threads = (Thread[])data[0];
List<Thread> lthreads = filteredThread(threads);
if (lthreads.size() == expectedChildCount) {
return;
}
Thread.sleep(1000);
}
Object[] data = getThreadGroupChildren(tg);
Thread[] threads = (Thread[])data[0];
System.out.println(Arrays.toString(threads));
throw new RuntimeException("Waited unsuccessfully for " + expectedChildCount + " children.");
}
private final static Comparator<Thread> THREAD_COMP = new Comparator<Thread>() {
public int compare(Thread o1, Thread o2) {
return o1.getName().compareTo(o2.getName());
}
};
private final static Comparator<ThreadGroup> THREADGROUP_COMP = new Comparator<ThreadGroup>() {
public int compare(ThreadGroup o1, ThreadGroup o2) {
return o1.getName().compareTo(o2.getName());
}
};
private static native ThreadGroup[] getTopThreadGroups();
private static native Object[] getThreadGroupInfo(ThreadGroup tg);
// Returns an array where element 0 is an array of threads and element 1 is an array of groups.
private static native Object[] getThreadGroupChildren(ThreadGroup tg);
}