java獲取當(dāng)前代碼運(yùn)行位置

1. Thread.dumpStack()

偶然看到 public static void dumpStack() 方法可以打印當(dāng)前代碼運(yùn)行位置

java.lang.Thread.dumpStack()實(shí)際實(shí)現(xiàn)是:new Exception("Stack trace").printStackTrace();

通過追蹤java.lang.Exception.Exception()杈绸,發(fā)現(xiàn)最終執(zhí)行的是 java.lang.Throwable.fillInStackTrace()方法

fillInStackTrace() 又調(diào)用了 private native Throwable fillInStackTrace(int dummy);

從文檔上看應(yīng)該几苍,這個(gè)方法是將當(dāng)前調(diào)用棧寫入到java.lang.Throwable.stackTrace內(nèi)
Throwable|fillInStackTrace()
Fills in the execution stack trace.

java.lang.Throwable.printStackTrace(PrintStreamOrWriter) 方法看,最終打印到java.lang.System.err中的是java.lang.StackTraceElement.toString()

依次調(diào)用printStackTrace()->printStackTrace(PrintStream s)->printStackTrace(PrintStreamOrWriter s)

java.lang.StackTraceElement.toString()

2.Thread.currentThread().getStackTrace()

java.lang.Thread.dumpStack() 類似的有 java.lang.Thread.getStackTrace() 方法纪铺,我們可以看到這個(gè)方法返回的也是java.lang.Throwable.stackTrace钻哩,要通過這個(gè)方法獲得相關(guān)信息的可以參考這篇文章:
Java: 獲取當(dāng)前執(zhí)行位置的文件名/類名/方法名/行號

java.lang.Thread.getStackTrace()實(shí)際返回的是stacketTrace

通過這個(gè)方法可以獲得其他線程正在執(zhí)行的代碼位置:

    public static void main(String[] args) {
        Thread th = new Thread() {
            @Override
            public void run() {
                while (true) {
                    System.out.println("hello");
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        th.start();
        while (true) {
            StackTraceElement[] ste = th.getStackTrace();
            System.out.println(ste.length);
            for (StackTraceElement stackTraceElement : ste) {
                System.out.println(stackTraceElement);
            }
        }
    }

通過在日志中搜索:hello屹堰,可以看到以下信息:

hello
13
java.io.FileOutputStream.writeBytes(Native Method)
java.io.FileOutputStream.write(Unknown Source)
java.io.BufferedOutputStream.flushBuffer(Unknown Source)
java.io.BufferedOutputStream.flush(Unknown Source)
java.io.PrintStream.write(Unknown Source)
sun.nio.cs.StreamEncoder.writeBytes(Unknown Source)
sun.nio.cs.StreamEncoder.implFlushBuffer(Unknown Source)
sun.nio.cs.StreamEncoder.flushBuffer(Unknown Source)
java.io.OutputStreamWriter.flushBuffer(Unknown Source)
java.io.PrintStream.write(Unknown Source)
java.io.PrintStream.print(Unknown Source)
java.io.PrintStream.println(Unknown Source)
com.demon.test.testStackTrace.Main$1.run(Main.java:12)
2
java.lang.Thread.sleep(Native Method)
com.demon.test.testStackTrace.Main$1.run(Main.java:14)

3.使用java.util.logging.LogRecord打印日志

使用java.util.logging.LogRecord打印日志,代碼和結(jié)果如下:可以看到打印了調(diào)用打印日志方法的類

Logger.getGlobal().log(Level.INFO, "Hello World");
--------------------------------------------------------
十二月 23, 2017 2:39:39 下午 com.demon.test.testlogger.Demo2 main
信息: Hello World

如果我們使用java.util.logging.XMLFormatter類將打印信息轉(zhuǎn)換為XML格式街氢,代碼和打印結(jié)果是這樣的:

        Logger log = Logger.getGlobal();
        ConsoleHandler consoleHandler = new ConsoleHandler();
        consoleHandler.setFormatter(new XMLFormatter());
        log.addHandler(consoleHandler);
        log.log(Level.INFO, "Hello World !!");
--------------------------------------------------------
<?xml version="1.0" encoding="GBK" standalone="no"?>
<!DOCTYPE log SYSTEM "logger.dtd">
<log>
<record>
  <date>2017-12-23T14:44:09</date>
  <millis>1514011449395</millis>
  <sequence>0</sequence>
  <logger>global</logger>
  <level>INFO</level>
  <class>com.demon.test.testlogger.Demo3</class>
  <method>main</method>
  <thread>1</thread>
  <message>Hello World !!</message>
</record>
十二月 23, 2017 2:44:09 下午 com.demon.test.testlogger.Demo3 main
信息: Hello World !!

class標(biāo)簽就是調(diào)用打印方法的類扯键,通過分析java.util.logging.XMLFormatter源代碼,可以知道珊肃,class標(biāo)簽的值打印的是 java.util.logging.LogRecord.sourceClassName荣刑,method對應(yīng)的java.util.logging.LogRecord.sourceMethodName

java.util.logging.LogRecord.getSourceClassName()

外界調(diào)用java.util.logging.LogRecord.getSourceClassName()java.util.logging.LogRecord.getSourceMethodName()時(shí)伦乔,如果沒有調(diào)用過java.util.logging.LogRecord.setSourceClassName(String)java.util.logging.LogRecord.setSourceMethodName(String)厉亏,就會調(diào)用java.util.logging.LogRecord.inferCaller()推斷java.util.logging.LogRecord.sourceClassNamejava.util.logging.LogRecord.sourceMethodName屬性并賦值

java.util.logging.LogRecord.inferCaller()和java.util.logging.LogRecord.isLoggerImplFrame(String)

可以看到這里也是通過 new Throwable();的方式來獲得調(diào)用打印日志方法的類和方法。
但是如果以為能通過 new LogRecord().getSourceClassName()的方式獲得當(dāng)前類和方法那就錯(cuò)了烈和,java.util.logging.LogRecord.inferCaller()內(nèi)部調(diào)用了java.util.logging.LogRecord.isLoggerImplFrame(String)
當(dāng)調(diào)用new LogRecord().getSourceClassName()時(shí)爱只,java.util.logging.LogRecord.isLoggerImplFrame(String)返回值永遠(yuǎn)都是false,在代碼行數(shù)為 549-572的for循環(huán)內(nèi)斥杜,lookingForLogger==true虱颗,由于isLoggerImpl==false,無法執(zhí)行代碼if (isLoggerImpl) {lookingForLogger = false;},lookingForLogger==false的情況就不會被執(zhí)行蔗喂,也就不會調(diào)用setSourceClassName(cname);setSourceMethodName(frame.getMethodName());

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市高帖,隨后出現(xiàn)的幾起案子缰儿,更是在濱河造成了極大的恐慌,老刑警劉巖散址,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件乖阵,死亡現(xiàn)場離奇詭異宣赔,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)瞪浸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進(jìn)店門儒将,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人对蒲,你說我怎么就攤上這事钩蚊。” “怎么了蹈矮?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵砰逻,是天一觀的道長。 經(jīng)常有香客問我泛鸟,道長蝠咆,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任北滥,我火速辦了婚禮刚操,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘再芋。我一直安慰自己菊霜,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布祝闻。 她就那樣靜靜地躺著占卧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪联喘。 梳的紋絲不亂的頭發(fā)上华蜒,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天,我揣著相機(jī)與錄音豁遭,去河邊找鬼叭喜。 笑死,一個(gè)胖子當(dāng)著我的面吹牛蓖谢,可吹牛的內(nèi)容都是我干的捂蕴。 我是一名探鬼主播,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼闪幽,長吁一口氣:“原來是場噩夢啊……” “哼啥辨!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起盯腌,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤溉知,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體级乍,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡舌劳,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了玫荣。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片甚淡。...
    茶點(diǎn)故事閱讀 38,599評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖捅厂,靈堂內(nèi)的尸體忽然破棺而出贯卦,到底是詐尸還是另有隱情,我是刑警寧澤恒傻,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布脸侥,位于F島的核電站,受9級特大地震影響盈厘,放射性物質(zhì)發(fā)生泄漏睁枕。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一沸手、第九天 我趴在偏房一處隱蔽的房頂上張望外遇。 院中可真熱鬧,春花似錦契吉、人聲如沸跳仿。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽菲语。三九已至,卻和暖如春惑灵,著一層夾襖步出監(jiān)牢的瞬間山上,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工英支, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留佩憾,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓干花,卻偏偏與公主長得像妄帘,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子池凄,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評論 2 348

推薦閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理抡驼,服務(wù)發(fā)現(xiàn),斷路器肿仑,智...
    卡卡羅2017閱讀 134,628評論 18 139
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法婶恼,類相關(guān)的語法桑阶,內(nèi)部類的語法柏副,繼承相關(guān)的語法勾邦,異常的語法,線程的語...
    子非魚_t_閱讀 31,598評論 18 399
  • 1割择、一個(gè)".java"源文件中是否可以包括多個(gè)類(不是內(nèi)部類)眷篇?有什么限制?答:可以有多個(gè)類荔泳,但只能有一個(gè)publ...
    岳小川閱讀 916評論 0 2
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,744評論 25 707
  • 教室里倒數(shù)第三張桌子 你回頭看我 我轉(zhuǎn)身看向墻角 黃昏 古井 街頭 通通躲開你 對你不起 沒想過要愛你 我預(yù)見你有...
    青霜歌閱讀 235評論 1 3