死鎖排查荞彼,內(nèi)存泄漏排查冈敛,cpu飆升,接口響應(yīng)慢(查看執(zhí)行時間)鸣皂,代碼未生效(查看線上代碼)抓谴,方法執(zhí)行異常(查看實時執(zhí)行結(jié)果)

常見命令

 #按照進程名字查找
 ps -aux | grep java

#強制殺死進程
 kill -9 pid

#按照端口號進行查找
 netstat -anp |grep 8080

#查看兩個機器是否聯(lián)通
 telnet ip 端口

 #查看開放的端口
 cat /etc/ssh/sshd_config
#跨服務(wù)器拷貝
scp -r xxx.jar root@ssh ip:/usr             -》root指的是ip所在的登錄用戶
scp -P 22222 -r xxx.jar root@ssh ip:/usr    -》指定端口號默認(rèn)22
scp -r xxx.jar root@ip:/usr                 -》省略寫ssh

#無日志輸出
 nohup java -jar xxx.jar > /dev/null 2> /dev/null &
#有日志輸出
 nohup java -jar xxx.jar > ./output.log &
#指定配置文件輸出
 nohup java -jar xxx.jar --spring.profiles.active=test2> ./output.log &
#查看日志
 tail -f ./output.log

#復(fù)雜搜索
grep
    定位
        grep '搜索內(nèi)容' 路徑開頭*   ->比如grep 'aa' ./*xxx.log 或者xxx*或者xxx.log
        搜索內(nèi)容復(fù)雜的可以用右邊替換 \\[projectName\\][[:space:]]is System*   ->英文中括號加反斜杠,空格用[[:space:]]替換寞缝,搜索內(nèi)容不要加引號
    前后
        grep -C 100 '搜索內(nèi)容' xxx* 搜索前后100行
        grep -A 10 -B 1 '搜索內(nèi)容' xxx* 搜索前一行后10行
tail
    tail -10f xxx.log   指定整個文件

1癌压、死鎖

 #性能排查
 https://blog.csdn.net/weixin_45549188/article/details/129629486
 #arthas教程
 https://arthas.aliyun.com/doc/quick-start.html


    /**
     //54-死鎖
 */
    // 創(chuàng)建兩個共享資源
    private static final String resource1 = new String();
    private static final Object resource2 = new Object();
    @GetMapping("lock")
    public void lock() {

        /**
         * 兩個線程 thread1 thread2
         * thread1對resource1上鎖,然后嘗試獲取resource2的鎖荆陆;
         * thread2對resource2上鎖滩届,然后嘗試獲取resource1的鎖;
         * 2個線程會相互等待被啼,出現(xiàn)死鎖
         */
        Thread thread1 = new Thread(() -> {
            synchronized (resource1) {
                System.out.println("Thread 1: Locked resource 1");

                try {
                    Thread.sleep(100); // 假設(shè)這里有其他操作帜消,需要一些時間
                } catch (Exception e) {
                    e.printStackTrace();
                }

                System.out.println("Thread 1: Attempting to lock resource 2");

                //嘗試索取resource2的鎖
                synchronized (resource2) {
                    System.out.println("Thread 1: Locked resource 2");
                }
            }
        }, "thread1");

        Thread thread2 = new Thread(() -> {
            synchronized (resource2) {
                System.out.println("Thread 2: Locked resource 2");

                try {
                    Thread.sleep(100); // 假設(shè)這里有其他操作,需要一些時間
                } catch (Exception e) {
                    e.printStackTrace();
                }

                //嘗試索取resource1的鎖
                System.out.println("Thread 2: Attempting to lock resource 1");
                synchronized (resource1) {
                    System.out.println("Thread 2: Locked resource 1");
                }
            }
        }, "thread2");

        // 啟動線程
        thread1.start();
        thread2.start();
    }
1-1浓体、【推薦】排查步驟(命令)方法1
   ps -aux | grep java
     #殺死進程繼續(xù)下一個測試
     kill -9 pid
     #以守護進程啟動
     nohup java -jar cpu-oom-test-1.0-SNAPSHOT.jar > ./output.log &

     #如果出現(xiàn)這個工具沒有的話
     -bash: pstack: command not found
     sudo yum install -y gdb
     
#直接輸入面程序查看死鎖
top
jstack pid
image.png
最后面就會出現(xiàn)發(fā)生死鎖的位置了(默認(rèn)敲完jstack命令就會滑到最后所以很容易就看到了)
image.png
1-2泡挺、使用arthas->方法2
 curl -O https://arthas.aliyun.com/arthas-boot.jar
     java -jar arthas-boot.jar
    #輸入你的java程序,回車

#直接輸入面程序查看死鎖
    thread -b
image.png
image.png

2汹碱、內(nèi)存泄漏

    

    /**
     //55-內(nèi)存泄露
     */
    public static List<byte[]> oomList = new ArrayList<>();
    @GetMapping("oom")
    public String oom() {
        while (true) {
            //不斷向列表中添加大對象, 10MB
            oomList.add(new byte[1024 * 1024 * 10]);
        }
    }

 //55-內(nèi)存泄露
     ps -aux | grep java
     #殺死進程繼續(xù)下一個測試
     kill -9 pid
     #以守護進程啟動
     nohup java -jar cpu-oom-test-1.0-SNAPSHOT.jar > ./output.log &

     top
#可以查看內(nèi)存占用情況
     jmap -heap pid

#使用arthas查看占用情況
dashboard
image.png
image.png
2-1【推薦】使用程序運行日志直接查看
這時候其實output.log里面也能看見是哪一行泄漏的
grep -A 10 -B 1 'OutOfMemory' output.log
image.png
2-2程序在運行之前就指定dump輸出(特點文件小粘衬,信息精準(zhǔn))
運行直接指定(設(shè)置內(nèi)存比較小方便測試)
     nohup java -jar -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./heap-dump.hprof -Xmx10m xxx.jar > ./output.log &

     #將上面的dump文件考出來

     #用visualvm工具進行分析,沒有的進行下載
     https://visualvm.github.io/index.html

用工具加載之后咳促,首頁就有泄漏的紅色標(biāo)記
     或者summary換成thread 視圖選擇文本直接搜memory就可以看到了

image.png

image.png
2-3 在運行的時候手動導(dǎo)出堆信息(特點文件大稚新,沒有直接溢出信息)【不推薦】
     #在運行導(dǎo)出日志文件【直接導(dǎo)出的文件大,而且查不見泄漏的進程跪腹,日志可以】
     jmap -dump:format=b,file=./dump.hprof pid

    #將上面的dump文件考出來

https://eclipse.dev/mat/
  #必須使用Eclipse MAT工具進行分析才行
(工具下載不下來換鏡像褂删,jdk必須17以上)
#Spring推薦的Liberica Open JDK下載地址-貝爾實驗室版本
https://bell-sw.com/pages/downloads/#jdk-8-lts
image.png
往下滑會提示有提示,只能大致推斷出是那個類冲茸,不能具體到哪一行
 Thread Stack信息里面顯示也是空空如也

image.png
image.png
如果結(jié)合visualvm分析的話屯阀,只能說也很難推斷出是哪一行吧缅帘,不推薦
image.png
image.png

3、cpu飆升


    /**
     //56-cpu飆升
     //常規(guī)排查和arthas-57

     */

    @GetMapping("cpu")
    public void test1() {
        System.out.println("程序已啟動");
        while (true) {
            ;
        }
    }
3-1常規(guī)方法(方法1)
 ps -aux | grep java
   #殺死進程繼續(xù)下一個測試
     kill -9 pid
     #以守護進程啟動
     nohup java -jar cpu-oom-test-1.0-SNAPSHOT.jar > ./output.log &

#使用top命令找到cpu飆升進程id
     top
     #根據(jù)進程id找到導(dǎo)致cpu飆升的線程
     ps H -eo pid,tid,%cpu | grep 進程id
     #將線程id轉(zhuǎn)換為16進制
     printf '0x%x\n' 線程id
     #根據(jù)線程定位問題代碼
     jstack 進程id | grep 16進制線程id -A 20


image.png

image.png

image.png

image.png

簡化【推薦难衰,省事】

創(chuàng)建一個腳本直接執(zhí)行钦无,把上面幾個步驟合起來
#!/bin/bash
# 獲取用戶輸入的進程 ID
read -p "請輸入要分析的Java進程ID: " pid
# 查找該進程下CPU使用率最高的線程(按CPU使用率降序排序取第一條)
top_thread=$(ps H -eo pid,tid,%cpu | grep $pid | sort -k3 -nr | head -n 1 | awk '{print $2}')
# 將線程ID轉(zhuǎn)換為十六進制
hex_thread=$(printf '0x%x\n' $top_thread)
# 使用jstack查找對應(yīng)線程的棧信息并輸出
jstack $pid | grep $hex_thread -A 20
image.png
3-2使用arthas(方法2)【推薦快】
  curl -O https://arthas.aliyun.com/arthas-boot.jar
     java -jar arthas-boot.jar
     #輸入你的java程序,回車
thread
#找到占用最高cpu的線程id

thread 線程id
image.png

image.png

4盖袭、arthas排查接口響應(yīng)慢失暂,代碼不生效,方法執(zhí)行異常

    /**
     //58-60-接口響應(yīng)慢-arthas
     */
    @GetMapping("slow")
    public void slow() throws InterruptedException {
        log.info("start");
        this.m1(100, "t1");
        this.m1(200, "t2");
        this.m1(1000, "t3");
        log.info("end");
    }

    private void m1(int minus, String name) throws InterruptedException {
        //休眠100毫秒
        TimeUnit.MILLISECONDS.sleep(minus);
        log.info(name);
    }
 ps -aux | grep java
     #殺死進程繼續(xù)下一個測試
     kill -9 pid
     #以守護進程啟動
     nohup java -jar cpu-oom-test-1.0-SNAPSHOT.jar > ./output.log &

     curl -O https://arthas.aliyun.com/arthas-boot.jar
     java -jar arthas-boot.jar
     #輸入你的java程序鳄虱,回車
4-1排查接口響應(yīng)慢
  #接口響應(yīng)慢排查
     【會顯示總共執(zhí)行時間是多少毫秒弟塞,每個步驟是多少毫秒】
     trace com.csw.cpuoom.controller.CpuOomController slow  -n 5 --skipJDKMethod false
     然后再掉一下接口觀察輸出
image.png

image.png
4-2、代碼未生效
      #檢查代碼未生效
     【會反編譯類獲取線上的代碼拙已,能看到線上代碼對不對】
     jad com.csw.cpuoom.controller.CpuOomControllerjadd
image.png
4-3方法執(zhí)行異常(執(zhí)行結(jié)果)
    /**
     62-查看方法執(zhí)行異常-atthas
     */
    @GetMapping("err")
    public  void err() throws InterruptedException {
        System.out.println("程序已啟動");
        for (int i = 1; i < 1000000; i++) {
            add(i, i + 1);
            TimeUnit.SECONDS.sleep(1);
        }
    }
    public static int add(int a, int b) {
        return a + b;
    }
#檢查方法執(zhí)行異常(執(zhí)行結(jié)果)
     【相當(dāng)于說能夠看到方法的實時請求和返回值】【先敲命令后掉接口】
     watch com.csw.cpuoom.controller.CpuOomController add "{params,returnObj}" -x 2 -n 999
image.png

image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末决记,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子倍踪,更是在濱河造成了極大的恐慌系宫,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件建车,死亡現(xiàn)場離奇詭異笙瑟,居然都是意外死亡,警方通過查閱死者的電腦和手機癞志,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來框产,“玉大人凄杯,你說我怎么就攤上這事”蓿” “怎么了戒突?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長描睦。 經(jīng)常有香客問我膊存,道長,這世上最難降的妖魔是什么忱叭? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任隔崎,我火速辦了婚禮,結(jié)果婚禮上韵丑,老公的妹妹穿的比我還像新娘爵卒。我一直安慰自己,他們只是感情好撵彻,可當(dāng)我...
    茶點故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布钓株。 她就那樣靜靜地躺著实牡,像睡著了一般。 火紅的嫁衣襯著肌膚如雪轴合。 梳的紋絲不亂的頭發(fā)上创坞,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天,我揣著相機與錄音受葛,去河邊找鬼题涨。 笑死,一個胖子當(dāng)著我的面吹牛奔坟,可吹牛的內(nèi)容都是我干的携栋。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼咳秉,長吁一口氣:“原來是場噩夢啊……” “哼婉支!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起澜建,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤向挖,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后炕舵,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體何之,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年咽筋,在試婚紗的時候發(fā)現(xiàn)自己被綠了溶推。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡奸攻,死狀恐怖蒜危,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情睹耐,我是刑警寧澤辐赞,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站硝训,受9級特大地震影響响委,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜窖梁,卻給世界環(huán)境...
    茶點故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一赘风、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧纵刘,春花似錦贝次、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽敲茄。三九已至,卻和暖如春山析,著一層夾襖步出監(jiān)牢的瞬間堰燎,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工笋轨, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留秆剪,地道東北人。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓爵政,卻偏偏與公主長得像仅讽,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子钾挟,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,933評論 2 355

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