(點選上方公眾號,可快速關註)
來源:Hengyunabc ,
hengyunabc.github.io/jvm-heap-dump-find-fd/
背景
最近排查一個檔案沒有關閉的問題,記錄一下。
哪些檔案沒有關閉是比較容易找到的,檢視行程的fd(File Descriptor)就可以。但是確定fd是在哪裡被開啟,在哪裡被取用的就複雜點,特別是在沒有重啟應用的情況下。
在JVM裡可以透過heap dump比較方便地反查物件的取用,從而找到洩露的程式碼。
以下麵簡單的demo為例,Demo會建立一個臨時檔案,並且沒有close掉:
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class Test {
public static void main(String[] args) throws IOException {
File tempFile = File.createTempFile(“test”, “ttt”);
FileInputStream fi = new FileInputStream(tempFile);
System.in.read();
}
}
透過檔案名查詢對應的fd
行程開啟的檔案在OS裡有對應的fd(File Descriptor),可以用lsof命令或者直接在linux下到/proc目錄下檢視。
以demo為例,可以找到test檔案的fd是12:
$ ls -alh /proc/11278/fd/
total 0
dr-x—— 2 admin users 0 Jun 30 18:20 .
dr-xr-xr-x 8 admin users 0 Jun 30 18:20 ..
lrwx—— 1 admin users 64 Jun 30 18:20 0 -> /dev/pts/0
lrwx—— 1 admin users 64 Jun 30 18:20 1 -> /dev/pts/0
lr-x—— 1 admin users 64 Jun 30 18:24 11 -> /dev/urandom
lr-x—— 1 admin users 64 Jun 30 18:24 12 -> /tmp/test7607712940880692142ttt
對行程進行heap dump
使用jmap命令:
jmap -dump:live,format=b,file=heap.bin 11278
透過OQL查詢java.io.FileDescriptor物件
對於每一個開啟的檔案在JVM裡都有一個java.io.FileDescriptor物件。檢視下原始碼,可以發現FileDescriptor裡有一個fd欄位:
public final class FileDescriptor {
private int fd;
所以需要查詢到fd等於12的FileDescriptor,QOL陳述句:
select s from java.io.FileDescriptor s where s.fd == 12
使用VisualVM裡的OQL控制檯查詢
在jdk8裡自帶VisualVM,jdk9之後可以單獨下載:https://visualvm.github.io/
把heap dump檔案匯入VisualVM裡,然後在“OQL控制檯”查詢上面的陳述句,結果是:
再可以查詢到parent,取用相關的物件。
使用jhat查詢
除了VisualVM還有其它很多heap dump工具,在jdk裡還自帶一個jhat工具,儘管在jdk9之後移除掉了,但是個人還是比較喜歡這個工具,因為它是一個web介面的。
jhat -port 7000 heap.bin
訪問 http://localhost:7000/oql/ ,可以在瀏覽器裡查詢OQL:
開啟連結可以檢視具體的資訊
總結
-
先找出沒有關閉檔案的fd
-
從heap dump裡據fd找出對應的java.io.FileDescriptor物件,再找到相關取用
連結
-
ViauslVM
https://visualvm.github.io/
-
Object Query Language (OQL)
http://cr.openjdk.java.net/~sundar/8022483/webrev.01/raw_files/new/src/share/classes/com/sun/tools/hat/resources/oqlhelp.html
【關於投稿】
如果大家有原創好文投稿,請直接給公號傳送留言。
① 留言格式:
【投稿】+《 文章標題》+ 文章連結
② 示例:
【投稿】《不要自稱是程式員,我十多年的 IT 職場總結》:http://blog.jobbole.com/94148/
③ 最後請附上您的個人簡介哈~
看完本文有收穫?請轉發分享給更多人
關註「ImportNew」,提升Java技能