blob: 048766604fcf8395fdda43a92229ce6ea18417b5 [file] [log] [blame]
Andreas Gampeaf13ab92017-01-11 20:57:40 -08001/*
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
17import java.util.Arrays;
Andreas Gampe72c19832017-01-12 13:22:16 -080018import java.util.ArrayList;
19import java.util.Collections;
20import java.util.concurrent.CountDownLatch;
21import java.util.HashMap;
22import java.util.List;
23import java.util.Map;
Andreas Gampeaf13ab92017-01-11 20:57:40 -080024
25public class Main {
26 public static void main(String[] args) throws Exception {
27 System.loadLibrary(args[1]);
28
29 doTest();
30 }
31
32 private static void doTest() throws Exception {
33 Thread t1 = Thread.currentThread();
34 Thread t2 = getCurrentThread();
35
36 if (t1 != t2) {
37 throw new RuntimeException("Expected " + t1 + " but got " + t2);
38 }
39 System.out.println("currentThread OK");
40
41 printThreadInfo(t1);
42 printThreadInfo(null);
43
44 Thread t3 = new Thread("Daemon Thread");
45 t3.setDaemon(true);
46 // Do not start this thread, yet.
47 printThreadInfo(t3);
48 // Start, and wait for it to die.
49 t3.start();
50 t3.join();
Andreas Gampe72c19832017-01-12 13:22:16 -080051 Thread.sleep(500); // Wait a little bit.
Andreas Gampeaf13ab92017-01-11 20:57:40 -080052 // Thread has died, check that we can still get info.
53 printThreadInfo(t3);
Andreas Gampe72c19832017-01-12 13:22:16 -080054
55 doStateTests();
56 }
57
58 private static class Holder {
59 volatile boolean flag = false;
60 }
61
62 private static void doStateTests() throws Exception {
63 System.out.println(Integer.toHexString(getThreadState(null)));
64 System.out.println(Integer.toHexString(getThreadState(Thread.currentThread())));
65
66 final CountDownLatch cdl1 = new CountDownLatch(1);
67 final CountDownLatch cdl2 = new CountDownLatch(1);
68 final CountDownLatch cdl3_1 = new CountDownLatch(1);
69 final CountDownLatch cdl3_2 = new CountDownLatch(1);
70 final CountDownLatch cdl4 = new CountDownLatch(1);
71 final CountDownLatch cdl5 = new CountDownLatch(1);
72 final Holder h = new Holder();
73 Runnable r = new Runnable() {
74 @Override
75 public void run() {
76 try {
77 cdl1.countDown();
78 synchronized(cdl1) {
79 cdl1.wait();
80 }
81
82 cdl2.countDown();
83 synchronized(cdl2) {
84 cdl2.wait(1000); // Wait a second.
85 }
86
87 cdl3_1.await();
88 cdl3_2.countDown();
89 synchronized(cdl3_2) {
90 // Nothing, just wanted to block on cdl3.
91 }
92
93 cdl4.countDown();
94 Thread.sleep(1000);
95
96 cdl5.countDown();
97 while (!h.flag) {
98 // Busy-loop.
99 }
100 } catch (Exception e) {
101 throw new RuntimeException(e);
102 }
103 }
104 };
105
106 Thread t = new Thread(r);
107 printThreadState(t);
108 t.start();
109
110 // Waiting.
111 cdl1.await();
112 Thread.yield();
113 Thread.sleep(100);
114 printThreadState(t);
115 synchronized(cdl1) {
116 cdl1.notifyAll();
117 }
118
119 // Timed waiting.
120 cdl2.await();
121 Thread.yield();
122 Thread.sleep(100);
123 printThreadState(t);
124 synchronized(cdl2) {
125 cdl2.notifyAll();
126 }
127
128 // Blocked on monitor.
129 synchronized(cdl3_2) {
130 cdl3_1.countDown();
131 cdl3_2.await();
132 Thread.yield();
133 Thread.sleep(100);
134 printThreadState(t);
135 }
136
137 // Sleeping.
138 cdl4.await();
139 Thread.yield();
140 Thread.sleep(100);
141 printThreadState(t);
142
143 // Running.
144 cdl5.await();
145 Thread.yield();
146 Thread.sleep(100);
147 printThreadState(t);
148 h.flag = true;
149
150 // Dying.
151 t.join();
152 Thread.yield();
153 Thread.sleep(100);
154
155 printThreadState(t);
156 }
157
158 private final static Map<Integer, String> STATE_NAMES = new HashMap<Integer, String>();
159 private final static List<Integer> STATE_KEYS = new ArrayList<Integer>();
160 static {
161 STATE_NAMES.put(0x1, "ALIVE");
162 STATE_NAMES.put(0x2, "TERMINATED");
163 STATE_NAMES.put(0x4, "RUNNABLE");
164 STATE_NAMES.put(0x400, "BLOCKED_ON_MONITOR_ENTER");
165 STATE_NAMES.put(0x80, "WAITING");
166 STATE_NAMES.put(0x10, "WAITING_INDEFINITELY");
167 STATE_NAMES.put(0x20, "WAITING_WITH_TIMEOUT");
168 STATE_NAMES.put(0x40, "SLEEPING");
169 STATE_NAMES.put(0x100, "IN_OBJECT_WAIT");
170 STATE_NAMES.put(0x200, "PARKED");
171 STATE_NAMES.put(0x100000, "SUSPENDED");
172 STATE_NAMES.put(0x200000, "INTERRUPTED");
173 STATE_NAMES.put(0x400000, "IN_NATIVE");
174 STATE_KEYS.addAll(STATE_NAMES.keySet());
175 Collections.sort(STATE_KEYS);
176 }
177
178 private static void printThreadState(Thread t) {
179 int state = getThreadState(t);
180
181 StringBuilder sb = new StringBuilder();
182
183 for (Integer i : STATE_KEYS) {
184 if ((state & i) != 0) {
185 if (sb.length()>0) {
186 sb.append('|');
187 }
188 sb.append(STATE_NAMES.get(i));
189 }
190 }
191
192 if (sb.length() == 0) {
193 sb.append("NEW");
194 }
195
196 System.out.println(Integer.toHexString(state) + " = " + sb.toString());
Andreas Gampeaf13ab92017-01-11 20:57:40 -0800197 }
198
199 private static void printThreadInfo(Thread t) {
200 Object[] threadInfo = getThreadInfo(t);
201 if (threadInfo == null || threadInfo.length != 5) {
202 System.out.println(Arrays.toString(threadInfo));
203 throw new RuntimeException("threadInfo length wrong");
204 }
205
206 System.out.println(threadInfo[0]); // Name
207 System.out.println(threadInfo[1]); // Priority
208 System.out.println(threadInfo[2]); // Daemon
209 System.out.println(threadInfo[3]); // Threadgroup
210 System.out.println(threadInfo[4] == null ? "null" : threadInfo[4].getClass()); // Context CL.
211 }
212
213 private static native Thread getCurrentThread();
214 private static native Object[] getThreadInfo(Thread t);
Andreas Gampe72c19832017-01-12 13:22:16 -0800215 private static native int getThreadState(Thread t);
Andreas Gampeaf13ab92017-01-11 20:57:40 -0800216}