1 /**
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19 package org.apache.hadoop.util;
20
21 import java.lang.reflect.Constructor;
22 import java.io;
23 import java.lang.management;
24 import java.util.Map;
25 import java.util.concurrent.ConcurrentHashMap;
26
27 import org.apache.commons.logging.Log;
28 import org.apache.hadoop.conf;
29 import org.apache.hadoop.mapred;
30
31 /**
32 * General reflection utils
33 */
34
35 public class ReflectionUtils {
36
37 private static final Class[] emptyArray = new Class[]{};
38 /**
39 * Cache of constructors for each class. Pins the classes so they
40 * can't be garbage collected until ReflectionUtils can be collected.
41 */
42 private static final Map<Class<?>, Constructor<?>> CONSTRUCTOR_CACHE =
43 new ConcurrentHashMap<Class<?>, Constructor<?>>();
44
45 /**
46 * Check and set 'configuration' if necessary.
47 *
48 * @param theObject object for which to set configuration
49 * @param conf Configuration
50 */
51 public static void setConf(Object theObject, Configuration conf) {
52 if (conf != null) {
53 if (theObject instanceof Configurable) {
54 ((Configurable) theObject).setConf(conf);
55 }
56 if (conf instanceof JobConf &&
57 theObject instanceof JobConfigurable) {
58 ((JobConfigurable)theObject).configure((JobConf) conf);
59 }
60 }
61 }
62
63 /** Create an object for the given class and initialize it from conf
64 *
65 * @param theClass class of which an object is created
66 * @param conf Configuration
67 * @return a new object
68 */
69 public static Object newInstance(Class<?> theClass, Configuration conf) {
70 Object result;
71 try {
72 Constructor meth = CONSTRUCTOR_CACHE.get(theClass);
73 if (meth == null) {
74 meth = theClass.getDeclaredConstructor(emptyArray);
75 meth.setAccessible(true);
76 CONSTRUCTOR_CACHE.put(theClass, meth);
77 }
78 result = meth.newInstance();
79 } catch (Exception e) {
80 throw new RuntimeException(e);
81 }
82 setConf(result, conf);
83 return result;
84 }
85
86 static private ThreadMXBean threadBean =
87 ManagementFactory.getThreadMXBean();
88
89 public static void setContentionTracing(boolean val) {
90 threadBean.setThreadContentionMonitoringEnabled(val);
91 }
92
93 private static String getTaskName(long id, String name) {
94 if (name == null) {
95 return Long.toString(id);
96 }
97 return id + " (" + name + ")";
98 }
99
100 /**
101 * Print all of the thread's information and stack traces.
102 *
103 * @param stream the stream to
104 * @param title a string title for the stack trace
105 */
106 public static void printThreadInfo(PrintWriter stream,
107 String title) {
108 final int STACK_DEPTH = 20;
109 boolean contention = threadBean.isThreadContentionMonitoringEnabled();
110 long[] threadIds = threadBean.getAllThreadIds();
111 stream.println("Process Thread Dump: " + title);
112 stream.println(threadIds.length + " active threads");
113 for (long tid: threadIds) {
114 ThreadInfo info = threadBean.getThreadInfo(tid, STACK_DEPTH);
115 if (info == null) {
116 stream.println(" Inactive");
117 continue;
118 }
119 stream.println("Thread " +
120 getTaskName(info.getThreadId(),
121 info.getThreadName()) + ":");
122 Thread.State state = info.getThreadState();
123 stream.println(" State: " + state);
124 stream.println(" Blocked count: " + info.getBlockedCount());
125 stream.println(" Waited count: " + info.getWaitedCount());
126 if (contention) {
127 stream.println(" Blocked time: " + info.getBlockedTime());
128 stream.println(" Waited time: " + info.getWaitedTime());
129 }
130 if (state == Thread.State.WAITING) {
131 stream.println(" Waiting on " + info.getLockName());
132 } else if (state == Thread.State.BLOCKED) {
133 stream.println(" Blocked on " + info.getLockName());
134 stream.println(" Blocked by " +
135 getTaskName(info.getLockOwnerId(),
136 info.getLockOwnerName()));
137 }
138 stream.println(" Stack:");
139 for (StackTraceElement frame: info.getStackTrace()) {
140 stream.println(" " + frame.toString());
141 }
142 }
143 stream.flush();
144 }
145
146 private static long previousLogTime = 0;
147
148 /**
149 * Log the current thread stacks at INFO level.
150 * @param log the logger that logs the stack trace
151 * @param title a descriptive title for the call stacks
152 * @param minInterval the minimum time from the last
153 */
154 public static synchronized void logThreadInfo(Log log,
155 String title,
156 long minInterval) {
157 if (log.isInfoEnabled()) {
158 long now = System.currentTimeMillis();
159 if (now - previousLogTime >= minInterval * 1000) {
160 previousLogTime = now;
161 ByteArrayOutputStream buffer = new ByteArrayOutputStream();
162 printThreadInfo(new PrintWriter(buffer), title);
163 log.info(buffer.toString());
164 }
165 }
166 }
167
168 // methods to support testing
169 static void clearCache() {
170 CONSTRUCTOR_CACHE.clear();
171 }
172
173 static int getCacheSize() {
174 return CONSTRUCTOR_CACHE.size();
175 }
176
177 }