3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
19 package org
.apache
.hadoop
.hbase
.util
;
21 import java
.io
.ByteArrayOutputStream
;
22 import java
.io
.PrintStream
;
23 import java
.io
.UnsupportedEncodingException
;
24 import java
.lang
.management
.ManagementFactory
;
25 import java
.lang
.management
.ThreadInfo
;
26 import java
.lang
.management
.ThreadMXBean
;
27 import java
.lang
.reflect
.Constructor
;
28 import java
.lang
.reflect
.InvocationTargetException
;
29 import java
.lang
.reflect
.Method
;
30 import java
.nio
.charset
.Charset
;
32 import org
.apache
.yetus
.audience
.InterfaceAudience
;
33 import org
.slf4j
.Logger
;
35 import edu
.umd
.cs
.findbugs
.annotations
.NonNull
;
37 @InterfaceAudience.Private
38 public class ReflectionUtils
{
39 @SuppressWarnings("unchecked")
40 public static <T
> T
instantiateWithCustomCtor(String className
,
41 Class
<?
>[] ctorArgTypes
, Object
[] ctorArgs
) {
43 Class
<?
extends T
> resultType
= (Class
<?
extends T
>) Class
.forName(className
);
44 Constructor
<?
extends T
> ctor
= resultType
.getDeclaredConstructor(ctorArgTypes
);
45 return instantiate(className
, ctor
, ctorArgs
);
46 } catch (ClassNotFoundException e
) {
47 throw new UnsupportedOperationException(
48 "Unable to find " + className
, e
);
49 } catch (NoSuchMethodException e
) {
50 throw new UnsupportedOperationException(
51 "Unable to find suitable constructor for class " + className
, e
);
55 private static <T
> T
instantiate(final String className
, Constructor
<T
> ctor
, Object
[] ctorArgs
) {
57 ctor
.setAccessible(true);
58 return ctor
.newInstance(ctorArgs
);
59 } catch (IllegalAccessException e
) {
60 throw new UnsupportedOperationException(
61 "Unable to access specified class " + className
, e
);
62 } catch (InstantiationException e
) {
63 throw new UnsupportedOperationException(
64 "Unable to instantiate specified class " + className
, e
);
65 } catch (InvocationTargetException e
) {
66 throw new UnsupportedOperationException(
67 "Constructor threw an exception for " + className
, e
);
71 public static <T
> T
newInstance(Class
<T
> type
, Object
... params
) {
72 return instantiate(type
.getName(), findConstructor(type
, params
), params
);
75 @SuppressWarnings("unchecked")
76 public static <T
> Constructor
<T
> findConstructor(Class
<T
> type
, Object
... paramTypes
) {
77 Constructor
<T
>[] constructors
= (Constructor
<T
>[]) type
.getDeclaredConstructors();
78 for (Constructor
<T
> ctor
: constructors
) {
79 Class
<?
>[] ctorParamTypes
= ctor
.getParameterTypes();
80 if (ctorParamTypes
.length
!= paramTypes
.length
) {
85 for (int i
= 0; i
< ctorParamTypes
.length
&& match
; ++i
) {
86 if (paramTypes
[i
] == null) {
87 match
= !ctorParamTypes
[i
].isPrimitive();
89 Class
<?
> paramType
= paramTypes
[i
].getClass();
90 match
= (!ctorParamTypes
[i
].isPrimitive()) ? ctorParamTypes
[i
].isAssignableFrom(paramType
)
91 : ((int.class.equals(ctorParamTypes
[i
]) && Integer
.class.equals(paramType
)) ||
92 (long.class.equals(ctorParamTypes
[i
]) && Long
.class.equals(paramType
)) ||
93 (double.class.equals(ctorParamTypes
[i
]) && Double
.class.equals(paramType
)) ||
94 (char.class.equals(ctorParamTypes
[i
]) && Character
.class.equals(paramType
)) ||
95 (short.class.equals(ctorParamTypes
[i
]) && Short
.class.equals(paramType
)) ||
96 (boolean.class.equals(ctorParamTypes
[i
]) && Boolean
.class.equals(paramType
)) ||
97 (byte.class.equals(ctorParamTypes
[i
]) && Byte
.class.equals(paramType
)));
105 throw new UnsupportedOperationException(
106 "Unable to find suitable constructor for class " + type
.getName());
109 /* synchronized on ReflectionUtils.class */
110 private static long previousLogTime
= 0;
111 private static final ThreadMXBean threadBean
= ManagementFactory
.getThreadMXBean();
114 * Log the current thread stacks at INFO level.
115 * @param log the logger that logs the stack trace
116 * @param title a descriptive title for the call stacks
117 * @param minInterval the minimum time from the last
119 public static void logThreadInfo(Logger log
,
122 boolean dumpStack
= false;
123 if (log
.isInfoEnabled()) {
124 synchronized (ReflectionUtils
.class) {
125 long now
= System
.currentTimeMillis();
126 if (now
- previousLogTime
>= minInterval
* 1000) {
127 previousLogTime
= now
;
133 ByteArrayOutputStream buffer
= new ByteArrayOutputStream();
134 printThreadInfo(new PrintStream(buffer
, false, "UTF-8"), title
);
135 log
.info(buffer
.toString(Charset
.defaultCharset().name()));
136 } catch (UnsupportedEncodingException ignored
) {
137 log
.warn("Could not write thread info about '" + title
+
138 "' due to a string encoding issue.");
145 * Print all of the thread's information and stack traces.
147 * @param stream the stream to
148 * @param title a string title for the stack trace
150 private static void printThreadInfo(PrintStream stream
,
152 final int STACK_DEPTH
= 20;
153 boolean contention
= threadBean
.isThreadContentionMonitoringEnabled();
154 long[] threadIds
= threadBean
.getAllThreadIds();
155 stream
.println("Process Thread Dump: " + title
);
156 stream
.println(threadIds
.length
+ " active threads");
157 for (long tid
: threadIds
) {
158 ThreadInfo info
= threadBean
.getThreadInfo(tid
, STACK_DEPTH
);
160 stream
.println(" Inactive");
163 stream
.println("Thread " +
164 getTaskName(info
.getThreadId(),
165 info
.getThreadName()) + ":");
166 Thread
.State state
= info
.getThreadState();
167 stream
.println(" State: " + state
);
168 stream
.println(" Blocked count: " + info
.getBlockedCount());
169 stream
.println(" Waited count: " + info
.getWaitedCount());
171 stream
.println(" Blocked time: " + info
.getBlockedTime());
172 stream
.println(" Waited time: " + info
.getWaitedTime());
174 if (state
== Thread
.State
.WAITING
) {
175 stream
.println(" Waiting on " + info
.getLockName());
176 } else if (state
== Thread
.State
.BLOCKED
) {
177 stream
.println(" Blocked on " + info
.getLockName());
178 stream
.println(" Blocked by " +
179 getTaskName(info
.getLockOwnerId(),
180 info
.getLockOwnerName()));
182 stream
.println(" Stack:");
183 for (StackTraceElement frame
: info
.getStackTrace()) {
184 stream
.println(" " + frame
.toString());
190 private static String
getTaskName(long id
, String name
) {
192 return Long
.toString(id
);
194 return id
+ " (" + name
+ ")";
198 * Get and invoke the target method from the given object with given parameters
199 * @param obj the object to get and invoke method from
200 * @param methodName the name of the method to invoke
201 * @param params the parameters for the method to invoke
202 * @return the return value of the method invocation
205 public static Object
invokeMethod(Object obj
, String methodName
, Object
... params
) {
208 m
= obj
.getClass().getMethod(methodName
, getParameterTypes(params
));
209 m
.setAccessible(true);
210 return m
.invoke(obj
, params
);
211 } catch (NoSuchMethodException e
) {
212 throw new UnsupportedOperationException("Cannot find specified method " + methodName
, e
);
213 } catch (IllegalAccessException e
) {
214 throw new UnsupportedOperationException("Unable to access specified method " + methodName
, e
);
215 } catch (IllegalArgumentException e
) {
216 throw new UnsupportedOperationException("Illegal arguments supplied for method " + methodName
,
218 } catch (InvocationTargetException e
) {
219 throw new UnsupportedOperationException("Method threw an exception for " + methodName
, e
);
223 private static Class
<?
>[] getParameterTypes(Object
[] params
) {
224 Class
<?
>[] parameterTypes
= new Class
<?
>[params
.length
];
225 for (int i
= 0; i
< params
.length
; i
++) {
226 parameterTypes
[i
] = params
[i
].getClass();
228 return parameterTypes
;