嗯...不确定这是否可能,但是如果您在单独的线程上运行,如何在 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 ms 的恒定时间操作,那么在主线程上是可以接受的。 最佳答案
编辑:
好的,您想避免堆栈跟踪。我环顾了一下:确定调用者的复杂性实际上在 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
进行子类化会起作用,但我有点疑问您为什么要这样做。也许用于调试,但这是我能想到的唯一用例。 (P.S. 我不得不更改堆栈跟踪中的偏移量。“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/