的注释中可以找到另一种解决方案这一增强请求..它使用getClassContext()习惯的方法SecurityManager似乎比堆栈跟踪方法更快。
下面的程序测试不同建议方法的速度(最有趣的部分在内部类中)SecurityManagerMethod):/**
* Test the speed of various methods for getting the caller class name
*/public class TestGetCallerClassName {
/**
* Abstract class for testing different methods of getting the caller class name
*/
private static abstract class GetCallerClassNameMethod {
public abstract String getCallerClassName(int callStackDepth);
public abstract String getMethodName();
}
/**
* Uses the internal Reflection class
*/
private static class ReflectionMethod extends GetCallerClassNameMethod {
public String getCallerClassName(int callStackDepth) {
return sun.reflect.Reflection.getCallerClass(callStackDepth).getName();
}
public String getMethodName() {
return "Reflection";
}
}
/**
* Get a stack trace from the current thread
*/
private static class ThreadStackTraceMethod extends GetCallerClassNameMethod {
public String getCallerClassName(int callStackDepth) {
return Thread.currentThread().getStackTrace()[callStackDepth].getClassName();
}
public String getMethodName() {
return "Current Thread StackTrace";
}
}
/**
* Get a stack trace from a new Throwable
*/
private static class ThrowableStackTraceMethod extends GetCallerClassNameMethod {
public String getCallerClassName(int callStackDepth) {
return new Throwable().getStackTrace()[callStackDepth].getClassName();
}
public String getMethodName() {
return "Throwable StackTrace";
}
}
/**
* Use the SecurityManager.getClassContext()
*/
private static class SecurityManagerMethod extends GetCallerClassNameMethod {
public String getCallerClassName(int callStackDepth) {
return mySecurityManager.getCallerClassName(callStackDepth);
}
public String getMethodName() {
return "SecurityManager";
}
/**
* A custom security manager that exposes the getClassContext() information
*/
static class MySecurityManager extends SecurityManager {
public String getCallerClassName(int callStackDepth) {
return getClassContext()[callStackDepth].getName();
}
}
private final static MySecurityManager mySecurityManager =
new MySecurityManager();
}
/**
* Test all four methods
*/
public static void main(String[] args) {
testMethod(new ReflectionMethod());
testMethod(new ThreadStackTraceMethod());
testMethod(new ThrowableStackTraceMethod());
testMethod(new SecurityManagerMethod());
}
private static void testMethod(GetCallerClassNameMethod method) {
long startTime = System.nanoTime();
String className = null;
for (int i = 0; i
className = method.getCallerClassName(2);
}
printElapsedTime(method.getMethodName(), startTime);
}
private static void printElapsedTime(String title, long startTime) {
System.out.println(title + ": " + ((double)(System.nanoTime() - startTime))/1000000 + " ms.");
}}
运行Java 1.6.0_17的2.4GHz Intel Core 2 Duo MacBook的输出示例:Reflection: 10.195 ms.Current Thread StackTrace: 5886.964 ms.Throwable StackTrace: 4700.073 ms.SecurityManager: 1046.804 ms.
内反射法是多比其他人都快。从新创建的堆栈跟踪Throwable比从电流中得到它更快Thread..以及在查找调用方类的非内部方法中,自定义。SecurityManager似乎是最快的。
更新
如李奥米指出本评论这个sun.reflect.Reflection.getCallerClass()方法默认情况下已在Java 7、UPDATE 40中禁用,并在Java 8中完全删除。阅读更多有关这方面的资料Java bug数据库中的这个问题.
更新2
如查姆比已经发现,甲骨文被迫退出改变移除sun.reflect.Reflection.getCallerClass()..Java 8中仍然可以使用它(但不推荐它)。
更新3
3年后:更新当前JVM的时间。> java -version
java version "1.8.0"Java(TM) SE Runtime Environment (build 1.8.0-b132)Java HotSpot(TM) 64-Bit Server VM (build 25.0-b70, mixed mode)>
java TestGetCallerClassNameReflection: 0.194s.Current Thread StackTrace: 3.887s.Throwable StackTrace: 3.173s.SecurityManager: 0.565s.