當前位置:首頁 » 編程語言 » java列印堆棧

java列印堆棧

發布時間: 2023-05-31 11:28:37

❶ android 怎麼列印函數堆棧 java

C++也是支持異常處理的,異常處理庫中,已經包含了獲取backtrace的介面,Android也是利用這個介面來列印堆棧信息的。在Android的C++中,已經集成了一個工具類CallStack,在libutils.so中。

使用方法:

[cpp]viewplain
#include<utils/CallStack.h>
...
CallStackstack;
stack.update();
stack.mp();

使用方式比較簡單。目前Andoid4.2版本已經將相關信息解析的很到位,符號表查找,demangle,偏移位置校正都做好了。

❷ 如何用Jstack把java進程中的堆棧信息輸出到

1.2 Thread Dump特點
1. 能在各種操作系統下使用
2. 能在各種Java應用伺服器下使用
3. 可以在生產環境下使用而不影響系統的性能
4. 可以將問題直接定位到應用程序的代碼行上

1.3 Thread Dump 能診斷的問題
1. 查找內存泄露,常見的是程序里load大量的數據到緩存
2. 發現死鎖線程;

1.4如何抓取Thread Dump
一般當伺服器掛起,崩潰或者性能底下時,就需要抓取伺服器的線程堆棧(Thread Dump)用於後續的分析. 在實際運行中,往往一次 mp的信息,還不足以確認問題。為了反映線程狀態的動態變化,需要接連多次做threadmp,每次間隔10-20s,建議至少產生三次 mp信息,如果每次 mp都指向同一個問題,我們才確定問題的典型性。

有很多方式可用於獲取ThreadDump, 下面列出一部分獲取方式:
操作系統命令獲取ThreadDump:
Windows:
1.轉向伺服器的標准輸出窗口並按下Control + Break組合鍵, 之後需要將線程堆棧復制到文件中;
UNIX/ linux
首先查找到伺服器的進程號(process id), 然後獲取線程堆棧.
1. ps –ef | grep java
2. kill -3 <pid>
注意:一定要謹慎, 一步不慎就可能讓伺服器進程被殺死。kill -9 命令會殺死進程。

❸ Java 異常中什麼是顯示堆棧軌跡

//方法出異常時會指明在那一行,顯示異常的堆棧軌跡
try {
String s[]={"1"};
s[1]="abc";
} catch (Exception e) {
e.printStackTrace();
}

//
e.printStackTrace();
就是列印出異常堆棧信息,你也可以不調用此條語句。如:
try {
String s[]={"1"};
s[1]="abc";
} catch (Exception e) {
System.out.print("出錯了"); }

❹ 原來jdk自帶了這么好玩的工具——使用 jstack定位死循環

線程快照是java虛擬機內每一個線程正在執行的方法堆棧的集合,生成線程快照的主要目的是用於定位線程出現問題的位置;常見的問題有

命令格式

jstack的option參數並不多,真正用到的也就三個,接下來我們一個個介紹一下

- -F :當線程掛起(Suspended)時,使用jstack -l pid命令是不會列印堆棧信息的,使用-F則可以強制輸出線程堆棧;但是會停止但
- -l :列印的信息除了堆棧外,還會顯示鎖芹梁返的附加信息;
- -m :同時輸出java和C/C++的堆棧信息;在java的系統類庫裡面,有很多方法都是native修飾的,這些native修飾的方法你在java層面是看不到源碼的,因為這些方法都是C/C++實現嫌飢的;

在線程的堆棧中,需要特別留意以下幾種狀態:

不帶option參數的命令

列印結果如下

第一行各個單詞的解析,

這里我們使用2個窗口,分別使用以下2個命令來測試

通過2個窗口對比可以看到,加了-l的命令多列印了鎖的信息;

一般情況下,如果程序出錯了, 都不會直接在生產環境的伺服器上找錯誤,這個時候就可以用到一個非常實用的功能,將堆棧快照導出來,然後到別的電腦上看,命令如下

執行後,就可以看到文件已經導出來了

通過cat命令可以看到,裡面的內容和我們在命令行輸出的內容是一樣的

首先我們准備好一個死循環的線程,在線程內定一個while的死循環,並且給這個線程起個名字為:yexindogn,阿里巴巴的開發規范裡面有一個規定,就是每個線程必須起一個名字,起名字就是為了 以後程序出問題的時候好找錯誤;

接著我們將此代碼打成jar包扔到linux伺服器上運行,直接輸入 java -jar Test.jar 命令即可運行,運行後我們可以看到控制台一直在輸出112這個字元,這就代表程序已經在運行了;

接著在看下CPU的運行情況,使用top命令查看cpu佔用情況,排在第一位的是進程號為30328的進程,佔用了6.6%的cpu; 這邊我使用了2個命令行連到同一台伺服器,一個窗口用來運行剛剛的jar包,另一個窗口用來查找錯誤;

知道進程號了,接著就是找線程了,輸入以下命令

列印結果如下,這里有一點需要注意,在我們加上-Hp指令後,PID展示就是線程的id了,這時候我們看到佔用CPU最高的線程id是30365;

還有另一種方式,就是使用ps命令來查找線程

通過這個命令我們可以看到這邊佔用最高的線程id也是30365 ;

以上的方式我們成功找到了佔用cpu高的線程id是30365,但這個id是十進制的,在這里需要先轉為16進制,輸入命令

計算出對應的16進制為:769d

當然也可以用其他的計算工具,比如mac系統自帶計算器就支持進制之間的轉換

在命令行輸入以下命令,這種方法更加快速,推薦使用

其中,grep 命令是查找結果為769d的內容,-A 20 表示列印匹配所在行的後20行內容。直接幫我們定位到所在線程的堆棧,結果如下

當然也可以用下面的死辦法,先列印出所有的堆棧快照;

列印結果如下

接著我用剛剛計算出來的16進制復制出來在這里搜索一下,經過查看就知道是我們剛剛起了名字為yexindong的線程出錯了,出錯的位置在Test.java的第13行代碼

我們看看java代碼,確實是第13行這里的死循環導致的

首先打開任務管理器,因為默認windows的任務管理器是不顯示進程pid的,所以我們需要設置一下,選擇 查看 選擇列(S)...

選中PID進程表示符後點擊確定按鈕

然後我們就可以看到佔用CPU最高的java進程PID為:976

因為windows不能直接查看java進程中的線程信息,所以我們需要藉助一個工具,渣指這個工具是微軟自己開發的,叫做Process Explorer ,網上很多,需要的童鞋請自行網路,打開後找到pid為976的進程右擊選擇 屬性

在彈出的窗口中找到線程這一欄,它的排序默認就是按照cpu佔用的率倒序排列的,所以最上面的就是佔用cpu最高的線程了,記住它的線程id:3548

剛剛拿到的進程id是十進制的,但是我們導出的jstack信息裡面,線程id是以16進制來展示的,所以我們要先將這個線程id為3548轉為16進制的,使用windows自帶的計算器即可,在快捷命令行輸入calc

計算器打開後將其設置為程序員使用的計算器

接著輸入線程id3548,在按一下16進制,就會自動進行轉換,結果為ddc,記住這個16進制;

在命令行輸入以下指令導出進程的堆棧快照信息

幾秒鍾後,快照導出了,靜靜地躺在文件夾里,等待著我們打開

用Notepad++打開導出的文件,搜索剛剛計算出來的16進制ddc,就可以定位到線程出錯的位置了

有些童鞋可能會覺得用這個jstack命令麻煩了,那java在代碼裡面可不可以列印出堆棧呢?你別說,還真有,就是這個方法:Thread.getAllStackTraces();光說不練假把式,來個demo測試一下吧

執行後列印結果如下,由此可以看到,將當前進程的所有線程都列印出來了,但是這邊只列印了簡單的堆棧信息,對於開發人員來說,已經起到了監控作用;

作為調優和找錯的工具來說,可以說jstack是用的最多的一個工具了,但是由於局限性,現在已經慢慢被替換掉了;大家更傾向於使用阿里巴巴開發的工具arthas;感興趣的童鞋可以了解下!

❺ slf4j怎麼列印java錯誤堆棧信息throwable對象

SLF4J 1.6.0以前的版本,如果列印異常堆棧信息,必雹和須用

log.error(Stringmsg,Throwablet)

log.info等對應方法.

如果msg含有變數,一般用String.format方法格式化msg.

如果用

error(Stringformat,Object...arguments)

等其它方法,異常堆棧信息會丟失.

幸好,SLF4J 1.6.0以後的版本對這個不友此肆團好的異常信息log改進了.

error(Stringformat,Object…arguments)這個方法也會列印異常堆棧信息,只不過規定throwable對象必須為

最後一個參數.如果不遵守這森橘個規定,異常堆棧信息不會log出來.

❻ kill-3生成的線程堆棧怎麼查看

第一步:在終端運行Java程序
第二步:通過命令 pidof java 找到已經啟動的java進程的ID,選擇需要查看的java程序的進程ID
第三步:使用命令 kill -3 <java進行的 pid> 列印出java程序的線程堆棧信息
第四步:通常情況下運行的項目可和賣迅能會比較大,那麼這個時候列印的堆棧信息可能會有幾千到幾萬行,為了方便查看,我們往往需要將輸出內容進行重定向
使用linux下的重定向命令方式即可:例如: demo.sh > run.log 2>&1 將輸出信息重定向到 run.log中。
註:在操作系統中,0 1 2分別對應著不同的含義, 如下:
0 : 標准輸入,即:C中的stdin , java中的System.in
1 : 標准輸出, 即:C中的stdout ,java中的配正System.out
2 : 錯誤輸出, 即:C中的stderr , java中的System.err

Demo:
----------------------------------------------------------------------------------------------
Sources Code :
public class PrintThreadTrace {

Object obj1 = new Object();
Object obj2 = new Object();

public void func1(){
synchronized (obj1){
func2();
}
}

public void func2(){
synchronized (obj2){
while(true){
System.out.print("");
}
}
}

public static void main(String[] args){
PrintThreadTrace ptt = new PrintThreadTrace();
ptt.func1();
}
}

----------------------------------------------------------------------------------------------------------------
按照步驟操作後喚此的列印輸出信息:

Full thread mp Java HotSpot(TM) 64-Bit Server VM (24.79-b02 mixed mode):

"Service Thread" daemon prio=10 tid=0x00007fdc880a9000 nid=0x12a4 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE

"C2 CompilerThread1" daemon prio=10 tid=0x00007fdc880a7000 nid=0x12a3 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE

"C2 CompilerThread0" daemon prio=10 tid=0x00007fdc880a4000 nid=0x12a2 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE

"JDWP Command Reader" daemon prio=10 tid=0x00007fdc50001000 nid=0x1299 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE

"JDWP Event Helper Thread" daemon prio=10 tid=0x00007fdc880a1800 nid=0x1298 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE

"JDWP Transport Listener: dt_socket" daemon prio=10 tid=0x00007fdc8809e000 nid=0x1297 runnable [0x0000000000000000]
java.lang.Thread.State: RUNNABLE

"Signal Dispatcher" daemon prio=10 tid=0x00007fdc88091000 nid=0x1296 waiting on condition [0x0000000000000000]
java.lang.Thread.State: RUNNABLE

"Finalizer" daemon prio=10 tid=0x00007fdc88071800 nid=0x1295 in Object.wait() [0x00007fdc77ffe000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000ecb04858> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135)
- locked <0x00000000ecb04858> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)

"Reference Handler" daemon prio=10 tid=0x00007fdc8806f800 nid=0x1294 in Object.wait() [0x00007fdc7c10b000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000ecb04470> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:503)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133)
- locked <0x00000000ecb04470> (a java.lang.ref.Reference$Lock)

"main" prio=10 tid=0x00007fdc8800b800 nid=0x128e runnable [0x00007fdc8fef7000]
java.lang.Thread.State: RUNNABLE
at com.wenchain.study.PrintThreadTrace.func2(PrintThreadTrace.java:20)
- locked <0x00000000ecc04b20> (a java.lang.Object)
at com.wenchain.study.PrintThreadTrace.func1(PrintThreadTrace.java:13)
- locked <0x00000000ecc04b10> (a java.lang.Object)
at com.wenchain.study.PrintThreadTrace.main(PrintThreadTrace.java:27)

"VM Thread" prio=10 tid=0x00007fdc8806b000 nid=0x1293 runnable

"GC task thread#0 (ParallelGC)" prio=10 tid=0x00007fdc88021000 nid=0x128f runnable

"GC task thread#1 (ParallelGC)" prio=10 tid=0x00007fdc88023000 nid=0x1290 runnable

"GC task thread#2 (ParallelGC)" prio=10 tid=0x00007fdc88024800 nid=0x1291 runnable

"GC task thread#3 (ParallelGC)" prio=10 tid=0x00007fdc88026800 nid=0x1292 runnable

"VM Periodic Task Thread" prio=10 tid=0x00007fdc880b3800 nid=0x12a5 waiting on condition

JNI global references: 1391

Heap
PSYoungGen total 17920K, used 1270K [0x00000000ecb00000, 0x00000000ede80000, 0x0000000100000000)
eden space 15872K, 8% used [0x00000000ecb00000,0x00000000ecc3d898,0x00000000eda80000)
from space 2048K, 0% used [0x00000000edc80000,0x00000000edc80000,0x00000000ede80000)
to space 2048K, 0% used [0x00000000eda80000,0x00000000eda80000,0x00000000edc80000)
ParOldGen total 39424K, used 0K [0x00000000c6200000, 0x00000000c8880000, 0x00000000ecb00000)
object space 39424K, 0% used [0x00000000c6200000,0x00000000c6200000,0x00000000c8880000)
PSPermGen total 21504K, used 2619K [0x00000000c1000000, 0x00000000c2500000, 0x00000000c6200000)
object space 21504K, 12% used [0x00000000c1000000,0x00000000c128edd8,0x00000000c2500000)

----------------------------------------------------------------------------------------------------------------------------
上面的信息中包含了當前JVM中所有運行的線程信息,其中在示例中我們啟動的線程為main線程,其餘的都是JVM自己創建的。
在列印的信息中,我們可以清楚的看見當前線程的調用上下文,可以很清楚的知道程序的運行情況。
並且我們在最後面還能看見當前虛擬機中的內存使用情況,青年世代,老年世代的信息等等...

PS: 在JDK1.5以上,我們可以通過在Java程序中調用Thread.getStackTrace()方法來進行堆棧的自動列印,使得線程堆棧的列印時機可編程控制。
文章知識點與官方知識檔案匹配
Java技能樹首頁概覽
89841 人正在系統學習中
點擊閱讀全文
打開CSDN,閱讀體驗更佳

jstack-查看Java進程的線程堆棧信息,鎖定高消耗資源代碼
jstack主要用來查看某個Java進程內的線程堆棧信息。語法格式如下: jstack[option]pid jstack[option]executable core jstack[option][server-id@]remote-hostname-or-ip 命令行參數選項說明如下: ...
011Java並發包018查看線程堆棧信息_執筆未來的博客
java.util.concurrent.ScheledThreadPoolExecutor$DelayedWorkQueue.take(ScheledThreadPoolExecutor.java:1088) java.util.concurrent.ScheledThreadPoolExecutor$DelayedWorkQueue.take(ScheledThreadPoolExecutor.java:809) java.util.concurre...
最新發布 jstack -- java堆棧常用排查指令
jstack -- java堆棧常用排查指令
繼續訪問

熱門推薦 jstack 命令查看JAVA線程堆棧
JAVA堆棧信息實際生產中,可能由於開發以及測試未能全面覆蓋的代碼質量、性能問題,而引致線程掛起甚至崩潰。可能就需要查看堆棧信息來排查問題了。jps -lvmjps -lvm 用於查看當前機器上運行的java進程。C:\Users\Administrator>jps -lvm 7348 -Dosgi.requiredJavaVersion=1.8 -Dosgi.instance.area.defa
繼續訪問
Java多線程——查看線程堆棧信息
Java多線程——查看線程堆棧信息 摘要:本文主要介紹了查看線程堆棧信息的方法。 使用Thread類的getAllStackTraces()方法 方法定義 可以看到getAllStackTraces()方法的返回值是一個Map對象,key是Thread的實例,value是一個StackTraceElement實例數組: 1 public static Map<Thread, S...
繼續訪問
java堆棧常用排查指令
java 異常排查四板斧 1、查看java 堆棧線程信息 說明 jstack命令列印指定Java進程、核心文件或遠程調試伺服器的Java線程的Java堆棧跟蹤信息。 對於每個Java框架,完整的類名,方法名, 位元組碼索引(BCI)和行號(如果有的話)被列印出來。 使用-m選項,jstack命令列印程序中所有線程的Java和本機幀 計數器(PC)。 對於每個本機幀,當可用時,將列印離PC最近的本機符號。 c++亂碼的名字不會被修改。 要demangle c++名稱,輸出這個 命令可以管道到c++filt。 當
繼續訪問
java診斷工具-Arthas(thread命令)查看當前線程堆棧
cpu使用率與linux 命令top -H -p <pid>的線程CPU類似 1、支持一鍵展示當前最忙的前N個線程並列印堆棧 thread -n 3 沒有線程ID,包含[Internal]表示為JVM內部線程,參考dashboard命令的介紹。 cpuUsage為采樣間隔時間內線程的CPU使用率,與dashboard命令的數據一致。 deltaTime為采樣間隔時間內線程的增量CPU時間,小於1ms時被取整顯示為0ms。 time線程運行總CPU...
繼續訪問

java查看線程的堆棧信息
通過使用jps 命令獲取需要監控的進程的pid,然後使用jstackpid 命令查看線程的堆棧信息。 通過jstack命令可以獲取當前進程的所有線程信息。 每個線程堆中信息中,都可以查看到線程ID、線程的狀態(wait、sleep、running 等狀態)、是否持有鎖信息等。 jstack -l <pid> >jvm_listlocks.txt 轉...
繼續訪問
java 查看線程堆棧信息_Java多線程——查看線程堆棧信息
java多線程——查看線程堆棧信息摘要:本文主要介紹了查看線程堆棧信息的方法。使用thread類的getallstacktraces()方法方法定義可以看到getallstacktraces()方法的返回值是一個map對象,key是thread的實例,value是一個stacktraceelement實例數組:1 public static map getallstacktraces()使用可以使...
繼續訪問
java線程堆棧信息分析
java堆棧信息分析
繼續訪問

java 查看堆棧_javap 命令查看堆棧中信息
javap命令是對.java文件進行反編譯,通過這個命令可以看到堆棧中是怎麼壓棧和出棧的已經執行順序,這里簡單解釋下javap的簡單的使用,下面舉個例子:題目:i++ 和++i的區別解釋:簡單點說 這個問題都不難回答,這里就不說了,但是實際上堆棧中區別也是老大了(這里就用到了javap命令), 步驟:1.在任意一個盤下面建一個名為Test.java的文件(文件名可以隨意命名)代碼如下:public...
繼續訪問
java 查看線程堆棧信息_jstack-查看Java進程的線程堆棧信息,鎖定高消耗資源代碼。...
jstack主要用來查看某個Java進程內的線程堆棧信息。語法格式如下:jstack[option]pidjstack[option]executablecorejstack[option][server-id@]remote-hostname-or-ip命令行參數選項說明如下:-llonglistings,會列印出額外的鎖信息,在發生死鎖時可以用jstack-lpid來觀察...
繼續訪問
java堆棧信息怎麼看_線程堆棧信息怎麼看? - cs_person的個人空間 - OSCHINA - 中文開源技術交流社區...
一條線程堆棧信息大概長成下面這個樣子:RMI TCP Connection(267865)-172.16.5.25" daemon prio=10 tid=0x00007fd508371000 nid=0x55ae waiting for monitor entry [0x00007fd4f8684000]java.lang.Thread.State: BLOCKED (on object m...
繼續訪問
線程堆棧信息怎麼看?
一條線程堆棧信息大概長成下面這個樣子: RMI TCP Connection(267865)-172.16.5.25" daemon prio=10 tid=0x00007fd508371000 nid=0x55ae waiting for monitor entry [0x00007fd...
繼續訪問
java的棧和堆
棧與堆都是Java用來在Ram中存放數據的地方。與C++不同,Java自動管理棧和堆,程序員不能直接地設置棧或堆。 Java 的堆是一個運行時數據區,類的(對象從中分配空間。這些對象通過new、newarray、anewarray和multianewarray等指令建立,它們不需要程序代碼來顯式的釋放。堆是由垃圾回收來負責的,堆的優勢是可以動態地分配內存大小,生存期也不必事先告訴編譯器,因為它是在...
繼續訪問
查看java線程_【JAVA】Java線程堆棧信息查看
如何獲得線程的堆棧信息?線上伺服器cpu 100%了,該如何排查問題?1.top命令查詢哪個pid進程佔用cpu高(ps -ef|grep java 獲取PID號)2.通過 top -Hp pid 可以查看該進程下各個線程的cpu使用情況,獲取佔用cpu高的線程id3.執行命令:printf "%X\n" 線程tid(用於獲取佔用cpu高的線程id的16進制數)4.執行命令:jstack pid ...
繼續訪問
kill -3 java_kill -3 PID命令獲取java應用堆棧信息
一、應用場景:當linux伺服器出現異常情況(響應緩慢,負載持續飆升)並且伺服器沒有安裝對應的包而無法使用jstack等命令時,可以使用linux的kill相關命令列印堆棧信息。命令格式:kill -3 PID二、執行步驟:2.1、獲取java進程的PIDps -ef|grep java結果的第二列數字就是進程對應的pid。2.2、kill -3 PID(1)如果項目通過Tomcat進行發布(普通...
繼續訪問
jstack 工具 查看JVM堆棧信息
1|0介紹 jstack是java虛擬機自帶的一種堆棧跟蹤工具。jstack用於列印出給定的java進程ID或corefile或遠程調試服務的Java堆棧信息,如果是在64位機器上,需要指定選項"-J-d64",Windows的jstack使用方式只支持以下的這種方式: jstack [-l] pid 主要分為兩個功能: a. 針對活著的進程做本地的或遠程的線程mp; b. 針對core文件做線程mp。 jstack用於生成java虛擬機當前時刻的線程快照。線程快照是...
繼續訪問

linux查看java堆棧
1、查看JAVA進程JVM參數 jinfo -flags pid(進程號) -XX:CICompilerCount=2 最大的並行編譯數 -XX:InitialHeapSize=16777216 JVM 的初始堆內存大小 -XX:MaxHeapSize=257949696 JVM 的最大堆內存大小 -XX:MaxNewSize=85983232 -XX:MinHeapDeltaBytes=196608 -XX:NewSize=5570560 -XX:OldSize=11206656 2、JVM 查看.
繼續訪問
Linux 如何查看一個進程的堆棧
有兩種方法:第一種:pstack 進程ID第二種,使用gdb 然後attach 進程ID,然後再使用命令 thread apply all bt 兩種方法都可以列出進程所有的線程的當前的調用棧。不過,使用gdb的方法,還可以查看某些信息,例如局部變數,指針等。不過,如果只看調用棧的話,pstack還是很方便的。
繼續訪問
JAVA獲取堆棧信息
1. 通過Throwable獲取 StackTraceElement[] stackTrace = new Throwable().getStackTrace(); 2. 通過Thread獲取 StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
繼續訪問
java 查看線程棧大小_基於 Java 線程棧的問題排查
除日誌外,還有沒有別的方式跟蹤線上服務問題呢?或者,跟蹤並排除日誌里無法發現的問題?方法當然是有的,就是通過現場快照定位並發現問題。我們所說的現場,主要指這兩方面:Java 線程棧。線程棧是Java線程工作的快照,可以獲得當前線程在做什麼;Java 內存堆。堆是JVM的內存快照,可以獲取內存分配相關信息。

❼ java jstack

java jstack是什麼,讓我們一起了解一下?

jstack是java虛擬機自帶的一種堆棧跟蹤工具,用於列印出給定的java進程ID或core file或遠程調試服務的Java堆棧信息,主要分為兩個功能:針對活著的進程做本地的或遠程的線程mp,以及針對core文件做線程mp。

jstack的概穗碼冊念是什麼?

1、jstack命令的語法格式:jstack

2、Dump文件:Dump文件是進程的內存鏡像。可以把程序的執行狀態通過調試器保存到mp文件中。Dump文件是用來給驅動程序編寫人員調試驅動程序用模禪的,這種文件必須用專門的工具軟體打開,比如使用Windbg。 

在Windbg中可以通過.mp命令保存進程的mp文件。比如下面的命令把當前進程的鏡像保存為c:\testmp.dmp文件:.mp /ma c:\testmp.dmp。 

其中、ma參數表示mp文件應該包含進程的完整信息,包括整個用戶態的內存,這樣mp文件尺寸會比較大,信息非常全面。如果不是用、ma參數,保存下來的mp文件只包含了部分重要資料,比如寄存器和線程棧空間,文件尺寸會比較小,無法分析所有的數據。 

3、java線程Dump:線程mp是非常有用的診斷java應用問題的工具,每一個java虛擬機都有及時生成顯示所有線程在某一點狀態的線程mp的能力。雖然各個java虛擬機線程mp列印輸出格式上略微有一些不同,但是線程mp出來的信息包含線程基本信息;線程的運行狀態、猜宏標識和調用的堆棧;調用的堆棧包含完整的類名,所執行的方法,如果可能的話還有源代碼的行數。

jstack是如何使用的?

實戰案例如下: package concurrency; import java.io.IOException; import java.io.InputStream; public class Test {     public static void main(String[] args) throws InterruptedException, IOException {         InputStream is = System.in;         int i = is.read();         System.out.println("exit。");     } }

❽ 如何在程序異常退出前輸出當前進程的堆棧信息 Backtraces

列印堆棧是調試的常用方法,一般在系統異常時,我們可以將異常情況下的堆棧列印出來,這樣十分方便錯誤查找。實際上還有另外一個非常有用的功能:分析代碼的行為。android代碼太過龐大復雜了,完全的靜態分析經常是無從下手,因此通過列印堆棧的動態分析也十分必要。

Android列印堆棧的方法,簡單歸類一下
1. zygote的堆棧mp
實際上這個可以同時mp java線程及native線程的堆棧,對於java線程,java堆棧和native堆棧都可以得到。
使用方法很簡單,直接在adb shell或串口中輸入:
[plain] view plain
kill -3 <pid>
輸出的trace會保存在 /data/anr/traces.txt文件中。這個需要注意,如果沒有 /data/anr/這個目錄或/data/anr/traces.txt這個文件,需要手工創建一下,並設置好讀寫許可權。
如果需要在代碼中,更容易控制堆棧的輸出時機,可以用以下命令獲取zygote的core mp:
[java] view plain
Process.sendSignal(pid, Process.SIGNAL_QUIT);
原理和命令行是一樣的。
不過需要注意兩點:
adb shell可能會沒有許可權,需要root。
android 4.2中關閉了native thread的堆棧列印,詳見 dalvik/vm/Thread.cpp的mpNativeThread方法:
[cpp] view plain
dvmPrintDebugMessage(target,
"\"%s\" sysTid=%d nice=%d sched=%d/%d cgrp=%s\n",
name, tid, getpriority(PRIO_PROCESS, tid),
schedStats.policy, schedStats.priority, schedStats.group);
mpSchedStat(target, tid);
// Temporarily disabled collecting native stacks from non-Dalvik
// threads because sometimes they misbehave.
//dvmDumpNativeStack(target, tid);
Native堆棧的列印被關掉了!不過對於大多數情況,可以直接將這個注釋打開。

2. debuggerd的堆棧mp
debuggerd是android的一個daemon進程,負責在進程異常出錯時,將進程的運行時信息mp出來供分析。debuggerd生 成的coremp數據是以文本形式呈現,被保存在 /data/tombstone/ 目錄下(名字取的也很形象,tombstone是墓碑的意思),共可保存10個文件,當超過10個時,會覆蓋重寫最早生成的文件。從4.2版本開 始,debuggerd同時也是一個實用工具:可以在不中斷進程執行的情況下列印當前進程的native堆棧。使用方法是:
[plain] view plain
debuggerd -b <pid>
這可以協助我們分析進程執行行為,但最最有用的地方是:它可以非常簡單的定位到native進程中鎖死或錯誤邏輯引起的死循環的代碼位置。

3. java代碼中列印堆棧
Java代碼列印堆棧比較簡單, 堆棧信息獲取和輸出,都可以通過Throwable類的方法實現。目前通用的做法是在java進程出現需要注意的異常時,列印堆棧,然後再決定退出或挽救。通常的方法是使用exception的printStackTrace()方法:
[java] view plain
try {
...
} catch (RemoteException e) {
e.printStackTrace();
...
}
當然也可以只列印堆棧不退出,這樣就比較方便分析代碼的動態運行情況。Java代碼中插入堆棧列印的方法如下:
[java] view plain
Log.d(TAG,Log.getStackTraceString(new Throwable()));

4. C++代碼中列印堆棧
C++也是支持異常處理的,異常處理庫中,已經包含了獲取backtrace的介面,Android也是利用這個介面來列印堆棧信息的。在Android的C++中,已經集成了一個工具類CallStack,在libutils.so中。使用方法:
[cpp] view plain
#include <utils/CallStack.h>
...
CallStack stack;
stack.update();
stack.mp();
使用方式比較簡單。目前Andoid4.2版本已經將相關信息解析的很到位,符號表查找,demangle,偏移位置校正都做好了。
[plain] view plain

5. C代碼中列印堆棧
C代碼,尤其是底層C庫,想要看到調用的堆棧信息,還是比較麻煩的。 CallStack肯定是不能用,一是因為其實C++寫的,需要重新封裝才能在C中使用,二是底層庫反調上層庫的函數,會造成鏈接器循環依賴而無法鏈接。 不過也不是沒有辦法,可以通過android工具類CallStack實現中使用的unwind調用及符號解析函數來處理。
這里需要注意的是,為解決鏈接問題,最好使用dlopen方式,查找需要用到的介面再直接調用,這樣會比較簡單。如下為相關的實現代碼,只需要在要 列印的文件中插入此部分代碼,然後調用getCallStack()即可,無需包含太多的頭文件和修改Android.mk文件:
[cpp] view plain
#define MAX_DEPTH 31
#define MAX_BACKTRACE_LINE_LENGTH 800
#define PATH "/system/lib/libcorkscrew.so"

typedef ssize_t (*unwindFn)(backtrace_frame_t*, size_t, size_t);
typedef void (*unwindSymbFn)(const backtrace_frame_t*, size_t, backtrace_symbol_t*);
typedef void (*unwindSymbFreeFn)(backtrace_symbol_t*, size_t);

static void *gHandle = NULL;

static int getCallStack(void){
ssize_t i = 0;
ssize_t result = 0;
ssize_t count;
backtrace_frame_t mStack[MAX_DEPTH];
backtrace_symbol_t symbols[MAX_DEPTH];

unwindFn unwind_backtrace = NULL;
unwindSymbFn get_backtrace_symbols = NULL;
unwindSymbFreeFn free_backtrace_symbols = NULL;

// open the so.
if(gHandle == NULL) gHandle = dlopen(PATH, RTLD_NOW);

// get the interface for unwind and symbol analyse
if(gHandle != NULL) unwind_backtrace = (unwindFn)dlsym(gHandle, "unwind_backtrace");
if(gHandle != NULL) get_backtrace_symbols = (unwindSymbFn)dlsym(gHandle, "get_backtrace_symbols");
if(gHandle != NULL) free_backtrace_symbols = (unwindSymbFreeFn)dlsym(gHandle, "free_backtrace_symbols");

if(!gHandle ||!unwind_backtrace ||!get_backtrace_symbols || !free_backtrace_symbols ){
ALOGE("Error! cannot get unwind info: handle:%p %p %p %p",
gHandle, unwind_backtrace, get_backtrace_symbols, free_backtrace_symbols );
return result;
}

count= unwind_backtrace(mStack, 1, MAX_DEPTH);
get_backtrace_symbols(mStack, count, symbols);

for (i = 0; i < count; i++) {
char line[MAX_BACKTRACE_LINE_LENGTH];

const char* mapName = symbols[i].map_name ? symbols[i].map_name : "<unknown>";
const char* symbolName =symbols[i].demangled_name ? symbols[i].demangled_name : symbols[i].symbol_name;
size_t fieldWidth = (MAX_BACKTRACE_LINE_LENGTH - 80) / 2;

if (symbolName) {
uint32_t pc_offset = symbols[i].relative_pc - symbols[i].relative_symbol_addr;
if (pc_offset) {
snprintf(line, MAX_BACKTRACE_LINE_LENGTH, "#%02d pc %08x %.*s (%.*s+%u)",
i, symbols[i].relative_pc, fieldWidth, mapName,
fieldWidth, symbolName, pc_offset);
} else {
snprintf(line, MAX_BACKTRACE_LINE_LENGTH, "#%02d pc %08x %.*s (%.*s)",
i, symbols[i].relative_pc, fieldWidth, mapName,
fieldWidth, symbolName);
}
} else {
snprintf(line, MAX_BACKTRACE_LINE_LENGTH, "#%02d pc %08x %.*s",
i, symbols[i].relative_pc, fieldWidth, mapName);
}

ALOGD("%s", line);
}

free_backtrace_symbols(symbols, count);

return result;
}
對sched_policy.c的堆棧調用分析如下,注意具體是否要列印,在哪裡列印,還可以通過pid、uid、property等來控制一下,這樣就不會被淹死在trace的汪洋大海中。
[plain] view plain
D/SchedPolicy( 1350): #00 pc 0000676c /system/lib/libcutils.so
D/SchedPolicy( 1350): #01 pc 00006b3a /system/lib/libcutils.so (set_sched_policy+49)
D/SchedPolicy( 1350): #02 pc 00010e82 /system/lib/libutils.so (androidSetThreadPriority+61)
D/SchedPolicy( 1350): #03 pc 00068104 /system/lib/libandroid_runtime.so (android_os_Process_setThreadPriority(_JNIEnv*, _jobject*, int, int)+7)
D/SchedPolicy( 1350): #04 pc 0001e510 /system/lib/libdvm.so (dvmPlatformInvoke+112)
D/SchedPolicy( 1350): #05 pc 0004d6aa /system/lib/libdvm.so (dvmCallJNIMethod(unsigned int const*, JValue*, Method const*, Thread*)+417)
D/SchedPolicy( 1350): #06 pc 00027920 /system/lib/libdvm.so
D/SchedPolicy( 1350): #07 pc 0002b7fc /system/lib/libdvm.so (dvmInterpret(Thread*, Method const*, JValue*)+184)
D/SchedPolicy( 1350): #08 pc 00060c30 /system/lib/libdvm.so (dvmCallMethodV(Thread*, Method const*, Object*, bool, JValue*, std::__va_list)+271)
D/SchedPolicy( 1350): #09 pc 0004cd34 /system/lib/libdvm.so
D/SchedPolicy( 1350): #10 pc 00049382 /system/lib/libandroid_runtime.so
D/SchedPolicy( 1350): #11 pc 00065e52 /system/lib/libandroid_runtime.so
D/SchedPolicy( 1350): #12 pc 0001435e /system/lib/libbinder.so (android::BBinder::transact(unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+57)
D/SchedPolicy( 1350): #13 pc 00016f5a /system/lib/libbinder.so (android::IPCThreadState::executeCommand(int)+513)
D/SchedPolicy( 1350): #14 pc 00017380 /system/lib/libbinder.so (android::IPCThreadState::joinThreadPool(bool)+183)
D/SchedPolicy( 1350): #15 pc 0001b160 /system/lib/libbinder.so
D/SchedPolicy( 1350): #16 pc 00011264 /system/lib/libutils.so (android::Thread::_threadLoop(void*)+111)
D/SchedPolicy( 1350): #17 pc 000469bc /system/lib/libandroid_runtime.so (android::AndroidRuntime::javaThreadShell(void*)+63)
D/SchedPolicy( 1350): #18 pc 00010dca /system/lib/libutils.so
D/SchedPolicy( 1350): #19 pc 0000e3d8 /system/lib/libc.so (__thread_entry+72)
D/SchedPolicy( 1350): #20 pc 0000dac4 /system/lib/libc.so (pthread_create+160)
D/SchedPolicy( 1350): #00 pc 0000676c /system/lib/libcutils.so
D/SchedPolicy( 1350): #01 pc 00006b3a /system/lib/libcutils.so (set_sched_policy+49)
D/SchedPolicy( 1350): #02 pc 00016f26 /system/lib/libbinder.so (android::IPCThreadState::executeCommand(int)+461)
D/SchedPolicy( 1350): #03 pc 00017380 /system/lib/libbinder.so (android::IPCThreadState::joinThreadPool(bool)+183)
D/SchedPolicy( 1350): #04 pc 0001b160 /system/lib/libbinder.so
D/SchedPolicy( 1350): #05 pc 00011264 /system/lib/libutils.so (android::Thread::_threadLoop(void*)+111)
D/SchedPolicy( 1350): #06 pc 000469bc /system/lib/libandroid_runtime.so (android::AndroidRuntime::javaThreadShell(void*)+63)
D/SchedPolicy( 1350): #07 pc 00010dca /system/lib/libutils.so
D/SchedPolicy( 1350): #08 pc 0000e3d8 /system/lib/libc.so (__thread_entry+72)
D/SchedPolicy( 1350): #09 pc 0000dac4 /system/lib/libc.so (pthread_create+160)

6. 其它堆棧信息查詢

熱點內容
內置存儲卡可以拆嗎 發布:2025-05-18 04:16:35 瀏覽:335
編譯原理課時設置 發布:2025-05-18 04:13:28 瀏覽:378
linux中進入ip地址伺服器 發布:2025-05-18 04:11:21 瀏覽:612
java用什麼軟體寫 發布:2025-05-18 03:56:19 瀏覽:31
linux配置vim編譯c 發布:2025-05-18 03:55:07 瀏覽:107
砸百鬼腳本 發布:2025-05-18 03:53:34 瀏覽:942
安卓手機如何拍視頻和蘋果一樣 發布:2025-05-18 03:40:47 瀏覽:739
為什麼安卓手機連不上蘋果7熱點 發布:2025-05-18 03:40:13 瀏覽:802
網卡訪問 發布:2025-05-18 03:35:04 瀏覽:510
接收和發送伺服器地址 發布:2025-05-18 03:33:48 瀏覽:371