1 /* 2 * Copyright (C) 2014 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 import java.lang.reflect.Field; 18 import java.util.Map; 19 20 public class Main implements Runnable { 21 static final int numberOfThreads = 5; 22 static final int totalOperations = 1000; 23 24 public static void main(String[] args) throws Exception { 25 final Thread[] threads = new Thread[numberOfThreads]; 26 for (int t = 0; t < threads.length; t++) { 27 threads[t] = new Thread(new Main()); 28 threads[t].start(); 29 } 30 for (Thread t : threads) { 31 t.join(); 32 } 33 // Do this test after the other part to leave some time for the heap task daemon to start 34 // up. 35 test_getStackTraces(); 36 System.out.println("Finishing"); 37 } 38 39 static Thread getHeapTaskDaemon() throws Exception { 40 Field f = ThreadGroup.class.getDeclaredField("systemThreadGroup"); 41 f.setAccessible(true); 42 ThreadGroup systemThreadGroup = (ThreadGroup) f.get(null); 43 44 while (true) { 45 int activeCount = systemThreadGroup.activeCount(); 46 Thread[] array = new Thread[activeCount]; 47 systemThreadGroup.enumerate(array); 48 for (Thread thread : array) { 49 if (thread.getName().equals("HeapTaskDaemon") && 50 thread.getState() != Thread.State.NEW) { 51 return thread; 52 } 53 } 54 // Yield to eventually get the daemon started. 55 Thread.sleep(10); 56 } 57 } 58 59 static void test_getStackTraces() throws Exception { 60 Thread heapDaemon = getHeapTaskDaemon(); 61 62 // Force a GC to ensure the daemon truly started. 63 Runtime.getRuntime().gc(); 64 // Check all the current threads for positive IDs. 65 Map<Thread, StackTraceElement[]> map = Thread.getAllStackTraces(); 66 for (Map.Entry<Thread, StackTraceElement[]> pair : map.entrySet()) { 67 Thread thread = pair.getKey(); 68 // Expect empty stack trace since we do not support suspending the GC thread for 69 // obtaining stack traces. See b/28261069. 70 if (thread == heapDaemon) { 71 System.out.println(thread.getName() + " depth " + pair.getValue().length); 72 } 73 } 74 } 75 76 public void test_getId() { 77 if (Thread.currentThread().getId() <= 0) { 78 System.out.println("current thread's ID is not positive"); 79 } 80 // Check all the current threads for positive IDs. 81 Map<Thread, StackTraceElement[]> stMap = Thread.getAllStackTraces(); 82 for (Thread thread : stMap.keySet()) { 83 if (thread.getId() <= 0) { 84 System.out.println("thread's ID is not positive: " + thread.getName()); 85 } 86 } 87 } 88 89 public void run() { 90 for (int i = 0; i < totalOperations; ++i) { 91 test_getId(); 92 } 93 } 94 } 95