嗯...不确定这是否可能,但是如果您在单独的线程上运行,如何在 Java 中获取真正调用者的类名(最好还有方法名)?我想将类名提取卸载到一个单独的线程(以免在我每秒执行 100 多个日志记录操作时阻塞 UI 线程)。
例如:
class Main {
public void callerMethod() {
Thread.currentThread().getStackTrace()[2].getMethodName(); // This gets me the caller. However, this is expensive to do on the UI Thread 100+ times per second. a call here can take up 70ms
new Thread(new Runnable() {
@Override
public void run() {
new SecondObject().iWantToKnowMyCaller();
}
}).start();
}
}
class SecondObject {
public void iWantToKnowMyCaller() {
// how do i get the caller method here so that it's "callerMethod" from "Main" ?
}
}
用例是这样的:我正在记录大量数据,我根本不想阻塞主线程。一些日志记录可能是快速且小的数据,但有些日志记录可能会转储很多东西。现在的问题还在于,按照代码的编写方式,callerMethod()
中有大约 600 多个入口点,因此重构将是一个相当大的挑战。
或者:
如果您可以证明 Thread.currentThread().getStackTrace()[2].getMethodName();
每次都保证是一个小于 5 毫秒的恒定时间操作,那么在主线程上是可以接受的。
最佳答案
编辑:
好的,你想避免堆栈跟踪。我环顾四周:确定调用者的复杂性实际上在 LogRecord
中。如果您可以通过 Logger.setSourceClassName()
手动设置调用者(任何字符串),那么 LogRecord 将不再构建堆栈跟踪来查找调用者的姓名。
public class ThreadTest
{
public static void main( String[] args )
{
LogRecord lr = new LogRecord( Level.INFO, "Hi" );
lr.setSourceClassName( "ThreadTest.main" ); // anything, including null
Logger.getAnonymousLogger().log( lr );
}
}
原答案:
子类化 Thread
会起作用,但我有点疑问您为什么要这样做。也许用于调试,但这是我能想到的唯一用例。 (附:我不得不更改堆栈跟踪中的偏移量。“2”将获得 callerMethod 的调用方——在下面的示例中为“main”。)
public class ThreadTest
{
public static void main( String[] args )
{
new Main().callerMethod();
}
}
class Main {
public void callerMethod() {
final String callee = Thread.currentThread().getStackTrace()[1].getMethodName(); // This gets me the caller
new MyThread(new Runnable() {
@Override
public void run() {
new SecondObject().iWantToKnowMyCaller();
}
}){
@Override
public String getInvoker() { return callee; }}.start();
}
}
abstract class MyThread extends Thread implements Invoker {
public MyThread( Runnable r )
{
super( r );
}
}
class SecondObject {
public void iWantToKnowMyCaller() {
// how do i get the caller method here so that it's "callerMethod" from "Main" ?
System.out.println( ((MyThread)(Thread.currentThread())).getInvoker() );
}
}
interface Invoker {
String getInvoker();
}
关于Java如何从单独的线程中获取调用者?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25736346/