阿里面試:Arthas原理和使用,大概說說吧?

文章很長,且持續更新,建議收藏起來,慢慢讀!瘋狂創客圈總目錄 博客園版 爲您奉上珍貴的學習資源 :

免費贈送 :《尼恩Java面試寶典》 持續更新+ 史上最全 + 面試必備 2000頁+ 面試必備 + 大廠必備 +漲薪必備
免費贈送 :《尼恩技術聖經+高併發系列PDF》 ,幫你 實現技術自由,完成職業升級, 薪酬猛漲!加尼恩免費領
免費贈送 經典圖書:《Java高併發核心編程(卷1)加強版》 面試必備 + 大廠必備 +漲薪必備 加尼恩免費領
免費贈送 經典圖書:《Java高併發核心編程(卷2)加強版》 面試必備 + 大廠必備 +漲薪必備 加尼恩免費領
免費贈送 經典圖書:《Java高併發核心編程(卷3)加強版》 面試必備 + 大廠必備 +漲薪必備 加尼恩免費領

免費贈送 資源寶庫: Java 必備 百度網盤資源大合集 價值>10000元 加尼恩領取


阿里面試:Arthas原理和使用,大概說說吧?

尼恩說在前面

在40歲老架構師 尼恩的讀者交流羣(50+)中,最近有小夥伴拿到了一線互聯網企業如阿里、滴滴、極兔、有贊、希音、百度、網易、美團的面試資格,遇到很多很重要的面試題:

Arthas原理和使用,大概說下吧?

Arthas 也是大家定位和解決線上問題,非常常用的一個工具。

所以,這個題目如果答不上來, 說明平時沒怎麼解決過線上問題, 面試基本就掛。

所以,這道題目,非常重要。

這裏,尼恩把這道面試題以及參考答案,做了詳細的梳理。 大家可以收藏起來, 時不時看看,做到溫故而知新。

同時,也收入咱們的 《尼恩Java面試寶典PDF》V159版本,供後面的小夥伴參考,提升大家的 3高 架構、設計、開發水平。

《尼恩 架構筆記》《尼恩高併發三部曲》《尼恩Java面試寶典》的PDF,請到公衆號【技術自由圈】獲取

本文目錄

目錄

Arthas 在線排錯工具的巨大價值

Arthas 是 Alibaba 開源的 Java 診斷工具,深受開發者喜愛。

通常,本地開發環境無法訪問生產環境。如果在生產環境中遇到問題,則無法使用 IDE 遠程調試。

更糟糕的是,在生產環境中調試是不可接受的,因爲它會暫停所有線程,導致服務暫停。

Arthas 旨在解決這些問題。開發人員可以通過Arthas 在線解決生產問題。通過Arthas ,無需 JVM 重啓,無需代碼更改。 Arthas 作爲觀察者永遠不會暫停正在運行的線程。

Arthas工具

Arthas 是一款線上監控診斷產品,通過全局視角實時查看應用 load、內存、gc、線程的狀態信息,並能在不修改應用代碼的情況下,對業務問題進行診斷,包括查看方法調用的出入參、異常,監測方法執行耗時,類加載信息等,大大提升線上問題排查效率。

Arthas中集成了大部分JDK工具的功能實現,因此,在線上情況時,可以通過它快速的幫助我們解決問題,如CPU佔用過高、線程阻塞、死鎖、代碼動態修改、方法執行緩慢、排查404等。

Arthas 官方文檔

當你遇到以下類似問題而束手無策時,Arthas可以幫助你解決

  • 這個類從哪個 jar 包加載的?爲什麼會報各種類相關的 Exception?
  • 我改的代碼爲什麼沒有執行到?難道是我沒 commit?分支搞錯了?
  • 遇到問題無法在線上 debug,難道只能通過加日誌再重新發布嗎?
  • 線上遇到某個用戶的數據處理有問題,但線上同樣無法 debug,線下無法重現!
  • 是否有一個全局視角來查看系統的運行狀況?
  • 有什麼辦法可以監控到JVM的實時運行狀態?
  • 怎麼快速定位應用的熱點,生成火焰圖?
  • 怎樣直接從JVM內查找某個類的實例?

Arthas支持JDK6+,支持Linux/Mac/Winodws,採用命令行交互模式,同時提供豐富的Tab自動補全功能,進一步方便進行問題的定位和診斷。

阿里提供的在線的Arthas Terminal學習方式(Arthas Tutorials (aliyun.com)),幫助大家快速上手。

arthas快速開始

方式一:使用 arthas-boot 啓動arthas

推薦使用arthas-boot(推薦),下載arthas-boot.jar,然後用java -jar的方式啓動:

curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar

打印幫助信息:

java -jar arthas-boot.jar -h

arthas-boot啓動過程中, 會下載一些依賴包,如果下載速度比較慢,可以使用aliyun的鏡像:

java -jar arthas-boot.jar --repo-mirror aliyun --use-http

arthas-boot 完成依賴下載,並且啓動。

啓動之後,這時候,arthas會列出當前檢測到的java進程,

Arthas會將本機中所有的Java進程查詢出來,類似於jps/ps的作用:

上面的例子中, 有一個 java進程, Arthas 自己的進程

30162  Arthas.jar

如果你的機器中啓動了多個Java應用,此時會查詢出來一個應用列表。

要操作那個進程,我們可以根據前面的序號進行輸入。

輸入選擇自己要操作的Java應用,如上情況中,再輸入1即可,並按回車鍵即可;

$ 1

最終,Arthas成功啓動,接下來再通過Arthas提供的指令進行操作即可:

方式二:使用 as.sh 腳本啓動arthas

Arthas 支持在 Linux/Unix/Mac 等平臺上一鍵安裝,有個專門的install.sh腳本

請複製以下內容,並粘貼到命令行中,敲 回車 執行即可:

curl -L https://arthas.aliyun.com/install.sh | sh

上述命令會下載啓動腳本文件 install.sh,並且下載 as.sh 到當前目錄,你可以放在任何地方或將其加入到 $PATH 中。

直接在shell下面執行./as.sh,就會進入交互界面。

也可以執行./as.sh -h來獲取更多參數信息。

arthas官方使用案例:

可以通過下面的方式自己動手實踐。

1、啓動 math-game

math-game是一個簡單的程序,每隔一秒生成一個隨機數,再執行質因數分解,並打印出分解結果。
math-game源代碼:查看

curl -O https://arthas.aliyun.com/math-game.jar
java -jar math-game.jar

2、啓動 arthas

在命令行下面執行(使用和目標進程一致的用戶啓動,否則可能 attach 失敗):

curl -O https://arthas.aliyun.com/arthas-boot.jar
java -jar arthas-boot.jar --repo-mirror aliyun --use-http
  • 執行該程序的用戶需要和目標進程具有相同的權限。

    比如以admin用戶來執行:sudo su admin && java -jar arthas-boot.jarsudo -u admin -EH java -jar arthas-boot.jar

  • 如果 attach 不上目標進程,可以查看~/logs/arthas/ 目錄下的日誌。

  • 如果下載速度比較慢,可以使用 aliyun 的鏡像:java -jar arthas-boot.jar --repo-mirror aliyun --use-http

  • java -jar arthas-boot.jar -h 打印更多參數信息。

選擇應用 java 進程:

$ $ java -jar arthas-boot.jar
* [1]: 35542
  [2]: 71560 math-game.jar

math-game進程是第 2 個,則輸入 2,再輸入回車/enter

Arthas 會 attach 到目標進程上,並輸出日誌:

[INFO] Try to attach process 71560
[INFO] Attach process 71560 success.
[INFO] arthas-client connect 127.0.0.1 3658
  ,---.  ,------. ,--------.,--.  ,--.  ,---.   ,---.
 /  O  \ |  .--. ''--.  .--'|  '--'  | /  O  \ '   .-'
|  .-.  ||  '--'.'   |  |   |  .--.  ||  .-.  |`.  `-.
|  | |  ||  |\  \    |  |   |  |  |  ||  | |  |.-'    |
`--' `--'`--' '--'   `--'   `--'  `--'`--' `--'`-----'


wiki: https://arthas.aliyun.com/doc
version: 3.0.5.20181127201536
pid: 71560
time: 2018-11-28 19:16:24

$

3、dashboard 展示當前進程的信息

輸入 dashboard,按回車/enter,會展示當前進程的信息,按ctrl+c可以中斷執行。

$ dashboard
ID     NAME                   GROUP          PRIORI STATE  %CPU    TIME   INTERRU DAEMON
17     pool-2-thread-1        system         5      WAITIN 67      0:0    false   false
27     Timer-for-arthas-dashb system         10     RUNNAB 32      0:0    false   true
11     AsyncAppender-Worker-a system         9      WAITIN 0       0:0    false   true
9      Attach Listener        system         9      RUNNAB 0       0:0    false   true
3      Finalizer              system         8      WAITIN 0       0:0    false   true
2      Reference Handler      system         10     WAITIN 0       0:0    false   true
4      Signal Dispatcher      system         9      RUNNAB 0       0:0    false   true
26     as-command-execute-dae system         10     TIMED_ 0       0:0    false   true
13     job-timeout            system         9      TIMED_ 0       0:0    false   true
1      main                   main           5      TIMED_ 0       0:0    false   false
14     nioEventLoopGroup-2-1  system         10     RUNNAB 0       0:0    false   false
18     nioEventLoopGroup-2-2  system         10     RUNNAB 0       0:0    false   false
23     nioEventLoopGroup-2-3  system         10     RUNNAB 0       0:0    false   false
15     nioEventLoopGroup-3-1  system         10     RUNNAB 0       0:0    false   false
Memory             used   total max    usage GC
heap               32M    155M  1820M  1.77% gc.ps_scavenge.count  4
ps_eden_space      14M    65M   672M   2.21% gc.ps_scavenge.time(m 166
ps_survivor_space  4M     5M    5M           s)
ps_old_gen         12M    85M   1365M  0.91% gc.ps_marksweep.count 0
nonheap            20M    23M   -1           gc.ps_marksweep.time( 0
code_cache         3M     5M    240M   1.32% ms)
Runtime
os.name                Mac OS X
os.version             10.13.4
java.version           1.8.0_162
java.home              /Library/Java/JavaVir
                       tualMachines/jdk1.8.0
                       _162.jdk/Contents/Hom
                       e/jre

4、thread 命令Main Class

通過 thread 命令來獲取到math-game進程的 Main Class

thread 1會打印線程 ID 1 的棧,通常是 main 函數的線程。

$ thread 1 | grep 'main('
    at demo.MathGame.main(MathGame.java:17)

得到了 Main Class 的全路徑名稱 demo.MathGame

5、jad命令 來反編譯 Main Class

jad 全路徑名稱, 進行源碼的反編譯

$ jad demo.MathGame

ClassLoader:
+-sun.misc.Launcher$AppClassLoader@3d4eac69
  +-sun.misc.Launcher$ExtClassLoader@66350f69

Location:
/tmp/math-game.jar

/*
 * Decompiled with CFR 0_132.
 */
package demo;

import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;

public class MathGame {
    private static Random random = new Random();
    private int illegalArgumentCount = 0;

    public static void main(String[] args) throws InterruptedException {
        MathGame game = new MathGame();
        do {
            game.run();
            TimeUnit.SECONDS.sleep(1L);
        } while (true);
    }

    public void run() throws InterruptedException {
        try {
            int number = random.nextInt();
            List<Integer> primeFactors = this.primeFactors(number);
            MathGame.print(number, primeFactors);
        }
          .......
        return result;
    }
    
   public List<Integer> primeFactors(int number) {
        if (number < 2) {
            ++this.illegalArgumentCount;
            throw new IllegalArgumentException("number is: " + number + ", need >= 2");
        }
        ArrayList<Integer> result = new ArrayList<Integer>();
        int i = 2;
        while (i <= number) {
            if (number % i == 0) {
                result.add(i);
                number /= i;
                i = 2;
                continue;
            }
            ++i;
        }
        return result;
    }
}

Affect(row-cnt:1) cost in 970 ms.

6、watch

通過 watch命令來查看到指定函數的調用情況。

watch能觀察到的範圍爲:返回值拋出異常入參,通過編寫 OGNL 表達式進行對應變量的查看。

watch 命令 的手冊地址

例子,通過 watch命令來查看 demo.MathGame#primeFactors 函數的返回值:

$ watch demo.MathGame primeFactors returnObj
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 107 ms.
ts=2018-11-28 19:22:30; [cost=1.715367ms] result=null
ts=2018-11-28 19:22:31; [cost=0.185203ms] result=null
ts=2018-11-28 19:22:32; [cost=19.012416ms] result=@ArrayList[
    @Integer[5],
    @Integer[47],
    @Integer[2675531],
]
ts=2018-11-28 19:22:33; [cost=0.311395ms] result=@ArrayList[
    @Integer[2],
    @Integer[5],
    @Integer[317],
    @Integer[503],
    @Integer[887],
]
ts=2018-11-28 19:22:34; [cost=10.136007ms] result=@ArrayList[
    @Integer[2],
    @Integer[2],
    @Integer[3],
    @Integer[3],
    @Integer[31],
    @Integer[717593],
]
ts=2018-11-28 19:22:35; [cost=29.969732ms] result=@ArrayList[
    @Integer[5],
    @Integer[29],
    @Integer[7651739],
]

更多的功能可以查看進階教程在新窗口打開

7、退出 arthas

如果只是退出當前的連接,可以用quit或者exit命令。Attach 到目標進程上的 arthas 還會繼續運行,端口會保持開放,下次連接時可以直接連接上。

如果想完全退出 arthas,可以執行stop命令。

Arthas的核心命令詳解

Arthas從最初的發佈開始,隨着後續社區的活躍性增強及用戶羣體的不斷壯大,指令也越發完善與豐富,至目前爲止提供了基礎命令、JVM命令、class命令以及字節碼增強命令等幾大類。

1、基礎命令

  • base64 - base64 編碼轉換,和 linux 裏的 base64 命令類似
  • cat - 打印文件內容,和 linux 裏的 cat 命令類似
  • cls - 清空當前屏幕區域
  • echo - 打印參數,和 linux 裏的 echo 命令類似
  • grep - 匹配查找,和 linux 裏的 grep 命令類似
  • help - 查看命令幫助信息
  • history - 打印命令歷史
  • keymap - Arthas 快捷鍵列表及自定義快捷鍵
  • pwd - 返回當前的工作目錄,和 linux 命令類似
  • quit - 退出當前 Arthas 客戶端,其他 Arthas 客戶端不受影響
  • reset - 重置增強類,將被 Arthas 增強過的類全部還原,Arthas 服務端關閉時會重置所有增強過的類
  • session - 查看當前會話的信息
  • stop - 關閉 Arthas 服務端,所有 Arthas 客戶端全部退出
  • tee - 複製標準輸入到標準輸出和指定的文件,和 linux 裏的 tee 命令類似
  • version - 輸出當前目標 Java 進程所加載的 Arthas 版本號

2、類操作命令

2.1 sc 命令:

sc “Search-Class” 的簡寫,查看JVM已加載的類信息,這個命令能搜索出所有已經加載到 JVM 中的 Class 信息,

可選項如下:

  • class-pattern:類名錶達式匹配(必填),如sc java.lang.String
  • -E:開啓正則表達式匹配,默認爲通配符匹配。
  • -c:指定class的類加載器的哈希碼。
  • -d:顯示當前類的詳細信息,包含來源、聲明、類加載相關等信息。
  • -f:輸出當前類的屬性成員信息,與-d一同使用。
  • -x:指定輸出靜態變量時屬性的遍歷深度,默認爲0
  • -n:具有詳細信息的匹配類的最大數量(默認爲100)。

提示

class-pattern 支持全限定名,支持兩種格式:

  • com.taobao.test.AAA,

  • 也支持 com/taobao/test/AAA 這樣的格式,

這樣,我們從異常堆棧裏面把類名拷貝過來的時候,不需要在手動把/替換爲.啦。

sc 命令 使用參考

  • 模糊搜索
$ sc demo.*
demo.MathGame
Affect(row-cnt:1) cost in 55 ms.
  • 打印類的詳細信息
$ sc -d demo.MathGame
class-info        demo.MathGame
code-source       /private/tmp/math-game.jar
name              demo.MathGame
isInterface       false
isAnnotation      false
isEnum            false
isAnonymousClass  false
isArray           false
isLocalClass      false
isMemberClass     false
isPrimitive       false
isSynthetic       false
simple-name       MathGame
modifier          public
annotation
interfaces
super-class       +-java.lang.Object
class-loader      +-sun.misc.Launcher$AppClassLoader@3d4eac69
                  +-sun.misc.Launcher$ExtClassLoader@66350f69
classLoaderHash   3d4eac69

Affect(row-cnt:1) cost in 875 ms.
  • 打印出類的 Field 信息
  $ sc -d -f demo.MathGame
  class-info        demo.MathGame
  code-source       /private/tmp/math-game.jar
  name              demo.MathGame
  isInterface       false
  isAnnotation      false
  isEnum            false
  isAnonymousClass  false
  isArray           false
  isLocalClass      false
  isMemberClass     false
  isPrimitive       false
  isSynthetic       false
  simple-name       MathGame
  modifier          public
  annotation
  interfaces
  super-class       +-java.lang.Object
  class-loader      +-sun.misc.Launcher$AppClassLoader@3d4eac69
                      +-sun.misc.Launcher$ExtClassLoader@66350f69
  classLoaderHash   3d4eac69
  fields            modifierprivate,static
                    type    java.util.Random
                    name    random
                    value   java.util.Random@522b4
                            08a
  
                    modifierprivate
                    type    int
                    name    illegalArgumentCount
  
  
  Affect(row-cnt:1) cost in 19 ms.

2.2 sm 命令

“Search-Method” 的簡寫,這個命令能搜索出所有已經加載了 Class 信息的方法信息。

sm 命令只能看到由當前類所聲明 (declaring) 的方法,父類則無法看到。

sm:查看已加載類的方法信息,可選項如下:

  • class-pattern:類名錶達式匹配(必填),如sm java.lang.String
  • -E:開啓正則表達式匹配,默認爲通配符匹配。
  • -d:查看方法的詳細信息,配合方法名使用,如sm -d java.lang.String toString
  • -c:同sc -c作用相同。
  • -n:同sc -h作用相同。
參數說明
參數名稱 參數說明
class-pattern 類名錶達式匹配
method-pattern 方法名錶達式匹配
[d] 展示每個方法的詳細信息
[E] 開啓正則表達式匹配,默認爲通配符匹配
[c:] 指定 class 的 ClassLoader 的 hashcode
[classLoaderClass:] 指定執行表達式的 ClassLoader 的 class name
[n:] 具有詳細信息的匹配類的最大數量(默認爲 100)
使用參考
$ sm java.lang.String
java.lang.String-><init>
java.lang.String->equals
java.lang.String->toString
java.lang.String->hashCode
java.lang.String->compareTo
java.lang.String->indexOf
java.lang.String->valueOf
.......
Affect(row-cnt:44) cost in 1342 ms.
$ sm -d java.lang.String toString
 declaring-class  java.lang.String
 method-name      toString
 modifier         public
 annotation
 parameters
 return           java.lang.String
 exceptions

Affect(row-cnt:1) cost in 3 ms.

2.3 jad命令

jad 命令將 JVM 中實際運行的 class 的 byte code 反編譯成 java 代碼,便於你理解業務邏輯;如需批量下載指定包的目錄的 class 字節碼可以參考 dump

  • 在 Arthas Console 上,反編譯出來的源碼是帶語法高亮的,閱讀更方便

  • 當然,反編譯出來的 java 代碼可能會存在語法錯誤,但不影響你進行閱讀理解

jad:反編譯指定已加載類的源碼,可選項如下:

  • -c、-E都與前面的作用相同,舉幾個案例演示用法。
  • jad --source-only java.lang.String:只顯示反編譯後的Java源碼。
  • jad java.lang.String:反編譯指定類。
  • jad java.lang.String toString:反編譯指定類的某個方法。
參數說明參數說明
參數名稱 參數說明
class-pattern 類名錶達式匹配
[c:] 類所屬 ClassLoader 的 hashcode
[classLoaderClass:] 指定執行表達式的 ClassLoader 的 class name
[E] 開啓正則表達式匹配,默認爲通配符匹配

jad 全路徑名稱, 進行源碼的反編譯

前面有例子

$ jad demo.MathGame

ClassLoader:
+-sun.misc.Launcher$AppClassLoader@3d4eac69
  +-sun.misc.Launcher$ExtClassLoader@66350f69

Location:
/tmp/math-game.jar

/*
 * Decompiled with CFR 0_132.
 */
package demo;

...
public class MathGame {
    private static Random random = new Random();
    private int illegalArgumentCount = 0;
.....
}

Affect(row-cnt:1) cost in 970 ms.

2.4 mc命令

Memory Compiler/內存編譯器,編譯.java文件生成.class

mc:內存編譯器,編譯.java源文件爲.class類文件,可選項如下:

  • -c:指定類加載器(以哈希碼的方式指定)。
  • -d:指定編譯後的類文件輸出位置。

2.6 retransform命令

加載外部的.class文件,retransform (再轉化;插樁) jvm 已加載的類, 比如在線替換 類的方法。

retransform:起到 熱部署的作用,用於線上替換類方法。

注意點:

  • ①重新替換JVM中被加載的類時,不能新增方法或屬性。
  • ②正在執行的方法不能替換。

retransform 使用參考

   retransform /tmp/Test.class
   retransform -l
   retransform -d 1                    # delete retransform entry
   retransform --deleteAll             # delete all retransform entries
   retransform --classPattern demo.*   # triger retransform classes
   retransform -c 327a647b /tmp/Test.class /tmp/Test\$Inner.class
   retransform --classLoaderClass 'sun.misc.Launcher$AppClassLoader' /tmp/Test.class

2.7 dump命令

dump`:導出已加載類的字節碼數據到指定目錄

dump 命令將 JVM 中實際運行的 class 的 byte code dump 到指定目錄,適用場景批量下載指定包目錄的 class 字節碼;如需反編譯單一類、實時查看類信息,可參考 jad

dump命令可選項如下:

  • -c、-E作用與之前的相同。
  • -d:指定輸出的路徑,如dump -d /usr/data/byteCode java.lang.String
參數說明
參數名稱 參數說明
class-pattern 類名錶達式匹配
[c:] 類所屬 ClassLoader 的 hashcode
[classLoaderClass:] 指定執行表達式的 ClassLoader 的 class name
[d:] 設置類文件的目標目錄
[E] 開啓正則表達式匹配,默認爲通配符匹配
使用參考
$ dump java.lang.String
 HASHCODE  CLASSLOADER  LOCATION
 null                   /Users/admin/logs/arthas/classdump/java/lang/String.class
Affect(row-cnt:1) cost in 119 ms.

2.8 classloader命令

classloader:查類加載器的繼承樹,urls,類加載信息,

classloader 命令將 JVM 中所有的 classloader 的信息統計出來,並可以展示繼承樹,urls 等。

可以讓指定的 classloader 去 getResources,打印出所有查找到的 resources 的 url。對於ResourceNotFoundException比較有用。

classloader 可選項如下:

  • -a:顯示所有類加載器加載的所有類。
  • -c:查看指定的類加載器的加載路徑,如classloader -c 14ae5a5
  • -l:統計每個類加載器的加載信息。
  • -r:查找某個的資源路徑,配合-c使用,如classloader -c 33909752 -r java/lang/String.class
  • -t:以樹結構列出每個類加載器之間的父子關係。
  • -u:顯示類加載器的url統計信息,如加載總數、父子關係、加載範圍等。
  • -i:查看每種類加載器的實例數量及其加載總量。
使用參考

按類加載類型查看統計信息

$ classloader
 name                                       numberOfInstances  loadedCountTotal
 com.taobao.arthas.agent.ArthasClassloader  1                  2115
 BootstrapClassLoader                       1                  1861
 sun.reflect.DelegatingClassLoader          5                  5
 sun.misc.Launcher$AppClassLoader           1                  4
 sun.misc.Launcher$ExtClassLoader           1                  1
Affect(row-cnt:5) cost in 3 ms.

按類加載實例查看統計信息

$ classloader -l
 name                                                loadedCount  hash      parent
 BootstrapClassLoader                                1861         null      null
 com.taobao.arthas.agent.ArthasClassloader@68b31f0a  2115         68b31f0a  sun.misc.Launcher$ExtClassLoader@66350f69
 sun.misc.Launcher$AppClassLoader@3d4eac69           4            3d4eac69  sun.misc.Launcher$ExtClassLoader@66350f69
 sun.misc.Launcher$ExtClassLoader@66350f69           1            66350f69  null
Affect(row-cnt:4) cost in 2 ms.

查看 ClassLoader 的繼承樹

$ classloader -t
+-BootstrapClassLoader
+-sun.misc.Launcher$ExtClassLoader@66350f69
  +-com.taobao.arthas.agent.ArthasClassloader@68b31f0a
  +-sun.misc.Launcher$AppClassLoader@3d4eac69
Affect(row-cnt:4) cost in 3 ms.

查看 URLClassLoader 實際的 urls

$ classloader -c 3d4eac69
file:/private/tmp/math-game.jar
file:/Users/hengyunabc/.arthas/lib/3.0.5/arthas/arthas-agent.jar

Affect(row-cnt:9) cost in 3 ms.

注意 hashcode 是變化的,需要先查看當前的 ClassLoader 信息,提取對應 ClassLoader 的 hashcode。

對於只有唯一實例的 ClassLoader 可以通過 class name 指定,使用起來更加方便:

$ classloader --classLoaderClass sun.misc.Launcher$AppClassLoader
file:/private/tmp/math-game.jar
file:/Users/hengyunabc/.arthas/lib/3.0.5/arthas/arthas-agent.jar

Affect(row-cnt:9) cost in 3 ms.

使用 ClassLoader 去查找 resource

$ classloader -c 3d4eac69  -r META-INF/MANIFEST.MF
 jar:file:/System/Library/Java/Extensions/MRJToolkit.jar!/META-INF/MANIFEST.MF
 jar:file:/private/tmp/math-game.jar!/META-INF/MANIFEST.MF
 jar:file:/Users/hengyunabc/.arthas/lib/3.0.5/arthas/arthas-agent.jar!/META-INF/MANIFEST.MF

也可以嘗試查找類的 class 文件:

$ classloader -c 1b6d3586 -r java/lang/String.class
 jar:file:/Library/Java/JavaVirtualMachines/jdk1.8.0_60.jdk/Contents/Home/jre/lib/rt.jar!/java/lang/String.class

使用 ClassLoader 去加載類

$ classloader -c 3d4eac69 --load demo.MathGame
load class success.
 class-info        demo.MathGame
 code-source       /private/tmp/math-game.jar
 name              demo.MathGame
 isInterface       false
 isAnnotation      false
 isEnum            false
 isAnonymousClass  false
 isArray           false
 isLocalClass      false
 isMemberClass     false
 isPrimitive       false
 isSynthetic       false
 simple-name       MathGame
 modifier          public
 annotation
 interfaces
 super-class       +-java.lang.Object
 class-loader      +-sun.misc.Launcher$AppClassLoader@3d4eac69
                     +-sun.misc.Launcher$ExtClassLoader@66350f69
 classLoaderHash   3d4eac69

3、JVM操作的命令

3.1 dashboard命令

dashboard:當前系統的實時數據面板,資源監控儀表盤,

dashboard 包含線程、內存、GC、運行環境等信息, 按 ctrl+c 退出。

dashboard可選項如下:

  • -i:刷新實時數據的間隔時間,默認爲5000ms
  • -n:刷新實時數據的次數,默認爲一直持續刷新,按ctrl+c退出。

參數說明

參數名稱 參數說明
[i:] 刷新實時數據的時間間隔 (ms),默認 5000ms
[n:] 刷新實時數據的次數
使用參考
$ dashboard
ID   NAME                           GROUP           PRIORITY   STATE     %CPU      DELTA_TIME TIME      INTERRUPTE DAEMON
-1   C2 CompilerThread0             -               -1         -         1.55      0.077      0:8.684   false      true
53   Timer-for-arthas-dashboard-07b system          5          RUNNABLE  0.08      0.004      0:0.004   false      true
22   scheduling-1                   main            5          TIMED_WAI 0.06      0.003      0:0.287   false      false
-1   C1 CompilerThread0             -               -1         -         0.06      0.003      0:2.171   false      true
-1   VM Periodic Task Thread        -               -1         -         0.03      0.001      0:0.092   false      true
49   arthas-NettyHttpTelnetBootstra system          5          RUNNABLE  0.02      0.001      0:0.156   false      true
16   Catalina-utility-1             main            1          TIMED_WAI 0.0       0.000      0:0.029   false      false
-1   G1 Young RemSet Sampling       -               -1         -         0.0       0.000      0:0.019   false      true
17   Catalina-utility-2             main            1          WAITING   0.0       0.000      0:0.025   false      false
34   http-nio-8080-ClientPoller     main            5          RUNNABLE  0.0       0.000      0:0.016   false      true
23   http-nio-8080-BlockPoller      main            5          RUNNABLE  0.0       0.000      0:0.011   false      true
-1   VM Thread                      -               -1         -         0.0       0.000      0:0.032   false      true
-1   Service Thread                 -               -1         -         0.0       0.000      0:0.006   false      true
-1   GC Thread#5                    -               -1         -         0.0       0.000      0:0.043   false      true
Memory                     used     total    max      usage    GC
heap                       36M      70M      4096M    0.90%    gc.g1_young_generation.count   12
g1_eden_space              6M       18M      -1       33.33%                                  86
g1_old_gen                 30M      50M      4096M    0.74%    gc.g1_old_generation.count     0
g1_survivor_space          491K     2048K    -1       24.01%   gc.g1_old_generation.time(ms)  0
nonheap                    66M      69M      -1       96.56%
codeheap_'non-nmethods'    1M       2M       5M       22.39%
metaspace                  46M      47M      -1       98.01%
Runtime
os.name                                                        Mac OS X
os.version                                                     10.15.4
java.version                                                   15
java.home                                                      /Library/Java/JavaVirtualMachines/jdk-15.jdk/Contents/Home
systemload.average                                             10.68
processors                                                     8
uptime                                                         272s
數據說明
  • ID: Java 級別的線程 ID,注意,這個 ID 不能跟 jstack 中的 nativeID 一一對應。
  • NAME: 線程名
  • GROUP: 線程組名
  • PRIORITY: 線程優先級, 1~10 之間的數字,越大表示優先級越高
  • STATE: 線程的狀態
  • CPU%: 線程的 cpu 使用率。比如採樣間隔 1000ms,某個線程的增量 cpu 時間爲 100ms,則 cpu 使用率=100/1000=10%
  • DELTA_TIME: 上次採樣之後線程運行增量 CPU 時間,數據格式爲
  • TIME: 線程運行總 CPU 時間,數據格式爲分:秒
  • INTERRUPTED: 線程當前的中斷位狀態
  • DAEMON: 是否是 daemon 線程
JVM 內部線程

Java 8 之後支持獲取 JVM 內部線程 CPU 時間,這些線程只有名稱和 CPU 時間,沒有 ID 及狀態等信息(顯示 ID 爲-1)。

JVM 內部線程包括下面幾種:

  • JIT 編譯線程: 如 C1 CompilerThread0, C2 CompilerThread0
  • GC 線程: 如GC Thread0, G1 Young RemSet Sampling
  • 其它內部線程: 如VM Periodic Task Thread, VM Thread, Service Thread

通過內部線程可以觀測到 JVM 活動,如 GC、JIT 編譯等佔用 CPU 情況,方便了解 JVM 整體運行狀況。

  • 當 JVM 堆(heap)/元數據(metaspace)空間不足或 OOM 時,可以看到 GC 線程的 CPU 佔用率明顯高於其他的線程。
  • 當執行trace/watch/tt/redefine等命令後,可以看到 JIT 線程活動變得更頻繁。因爲 JVM 熱更新 class 字節碼時, 清除了此 class 相關的 JIT 編譯結果,需要重新編譯。

3.2 thread命令

查看當前線程信息,查看線程的堆棧

thread:查看當前線程的堆棧信息,可選項如下:

  • -n:顯示最活躍的n條線程信息,如thread -n 5
  • -i:指定活躍性統計的採樣間隔時間,如thread -i 5000
  • -b:自動檢測出應用中當前阻塞其他線程的線程。
  • --state:查詢目前程序中處於指定狀態的線程,如thread --state BLOCKED
  • id:查看某個線程的詳細信息,如thread 21

參數列表

參數名稱 參數說明
id 線程 id
[n:] 指定最忙的前 N 個線程並打印堆棧
[b] 找出當前阻塞其他線程的線程
[i <value>] 指定 cpu 使用率統計的採樣間隔,單位爲毫秒,默認值爲 200
[--all] 顯示所有匹配的線程
cpu 使用率是如何統計出來的?

這裏的 cpu 使用率與 linux 命令top -H -p <pid> 的線程%CPU類似,一段採樣間隔時間內,當前 JVM 裏各個線程的增量 cpu 時間與採樣間隔時間的比例。

工作原理說明:

  • 首先第一次採樣,獲取所有線程的 CPU 時間(調用的是java.lang.management.ThreadMXBean#getThreadCpuTime()sun.management.HotspotThreadMBean.getInternalThreadCpuTimes()接口)
  • 然後睡眠等待一個間隔時間(默認爲 200ms,可以通過-i指定間隔時間)
  • 再次第二次採樣,獲取所有線程的 CPU 時間,對比兩次採樣數據,計算出每個線程的增量 CPU 時間
  • 線程 CPU 使用率 = 線程增量 CPU 時間 / 採樣間隔時間 * 100%

注意

注意: 這個統計也會產生一定的開銷(JDK 這個接口本身開銷比較大),因此會看到 as 的線程佔用一定的百分比,爲了降低統計自身的開銷帶來的影響,可以把採樣間隔拉長一些,比如 5000 毫秒。

eg:支持一鍵展示當前最忙的前 N 個線程並打印堆棧:

$ thread -n 3
"C1 CompilerThread0" [Internal] cpuUsage=1.63% deltaTime=3ms time=1170ms


"arthas-command-execute" Id=23 cpuUsage=0.11% deltaTime=0ms time=401ms RUNNABLE
    at [email protected]/sun.management.ThreadImpl.dumpThreads0(Native Method)
    at [email protected]/sun.management.ThreadImpl.getThreadInfo(ThreadImpl.java:466)
    at com.taobao.arthas.core.command.monitor200.ThreadCommand.processTopBusyThreads(ThreadCommand.java:199)
    at com.taobao.arthas.core.command.monitor200.ThreadCommand.process(ThreadCommand.java:122)
    at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl.process(AnnotatedCommandImpl.java:82)
    at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl.access$100(AnnotatedCommandImpl.java:18)
    at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl$ProcessHandler.handle(AnnotatedCommandImpl.java:111)
    at com.taobao.arthas.core.shell.command.impl.AnnotatedCommandImpl$ProcessHandler.handle(AnnotatedCommandImpl.java:108)
    at com.taobao.arthas.core.shell.system.impl.ProcessImpl$CommandProcessTask.run(ProcessImpl.java:385)
    at [email protected]/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
    at [email protected]/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at [email protected]/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304)
    at [email protected]/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at [email protected]/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at [email protected]/java.lang.Thread.run(Thread.java:834)


"VM Periodic Task Thread" [Internal] cpuUsage=0.07% deltaTime=0ms time=584ms
  • 沒有線程 ID,包含[Internal]表示爲 JVM 內部線程,參考dashboard命令的介紹。
  • cpuUsage爲採樣間隔時間內線程的 CPU 使用率,與dashboard命令的數據一致。
  • deltaTime爲採樣間隔時間內線程的增量 CPU 時間,小於 1ms 時被取整顯示爲 0ms。
  • time 線程運行總 CPU 時間。

注意:線程棧爲第二採樣結束時獲取,不能表明採樣間隔時間內該線程都是在處理相同的任務。建議間隔時間不要太長,可能間隔時間越大越不準確。 可以根據具體情況嘗試指定不同的間隔時間,觀察輸出結果。

thread --all, 顯示所有匹配的線程

顯示所有匹配線程信息,有時需要獲取全部 JVM 的線程數據進行分析

3.3 jvm命令

jvm:查看JVM信息,包含線程/內存/OS/內存結構/編譯/類加載/運行環境等信息。

使用參考,請參見 官方文檔

jvm | arthas (aliyun.com)

3.4 sysprop命令

查看當前 JVM 的系統屬性(System Property)

sysprop java.home

使用參考,請參見 官方文檔

sysprop | arthas (aliyun.com)

3.5 sysenv命令

sysenv:,查看當前JVM的環境參數。

使用參考,請參見 官方文檔

sysenv | arthas (aliyun.com)

3.6 vmoption命令

vmoption:查看或修改JVM的運行時參數,如:

  • vmoption PrintGC:查看PrintGC是否開啓。
  • vmoption PrintGC true:更改PrintGC參數。

使用參考,請參見 官方文檔

vmoption | arthas (aliyun.com)

3.7 getstatic命令

getstatic:查看類的靜態屬性,用法:getstatic class_nmae field_name

使用參考,請參見 官方文檔

getstatic | arthas (aliyun.com)

3.8 ognl命令

ognl:執行ognl表達式

使用參考,請參見 官方文檔

ognl | arthas (aliyun.com)

3.9 heapdump命令

heapdump:類似於jmap工具的堆dump功能,使用方式:

  • heapdump /usr/data/dump/heap.hprof:導出堆快照到指定文件。
  • heapdump --live /usr/data/dump/heap.hprof:只導出存活對象的快照。

使用參考,請參見 官方文檔

heapdump | arthas (aliyun.com)

3.10 mbean命令

mbean:查看Mbean的信息

使用參考,請參見 官方文檔

mbean | arthas (aliyun.com)

3.11 memory命令

memory:查看JVM的內存劃分、內存結構以及佔用率。

使用參考,請參見 官方文檔

memory | arthas (aliyun.com)

4、字節碼增強命令

4.1 watch命令

讓你能方便的觀察到指定函數的調用情況。能觀察到的範圍爲:返回值拋出異常入參,通過編寫 OGNL 表達式進行對應變量的查看。

使用參考,請參見 官方文檔

watch | arthas (aliyun.com)

watch:觀測指定方法的執行情況,可選項如下:

  • -b:在方法調用之前觀測。
  • -s:在方法成功執行後觀測。
  • -e:在方法異常執行後觀測。
  • -f:在方法結束後進行觀測(默認)。
  • -n:指定觀測的次數。
  • 使用示例:watch -s -n 10 demo.MathGame primeFactors

4.2 tt 命令

watch 雖然很方便和靈活,但需要提前想清楚觀察表達式的拼寫,這對排查問題而言要求太高,因爲很多時候我們並不清楚問題出自於何方,只能靠蛛絲馬跡進行猜測。

這個時候如果能記錄下當時方法調用的所有入參和返回值、拋出的異常會對整個問題的思考與判斷非常有幫助。

於是乎,TimeTunnel 命令就誕生了。

tt

tt 全稱 TimeTunnel ,意思是 : 方法執行數據的時空隧道,

記錄指定方法每次執行的數據,並能在不同的時間下調用觀測,

記錄下指定方法每次調用的入參和返回信息,並能對這些不同的時間下調用進行觀測

使用參考,請參見 官方文檔

tt | arthas (aliyun.com)

tt命令可選項如下:

  • <class_pattern> <method_pattern>:指定要觀測的類名+方法名。
  • -t:記錄下方法每次執行的情況,如tt -t demo.MathGame primeFactors
  • -i <index>:查看某條執行記錄的執行詳情,如tt -i 1000
  • -d <index>:刪除某條執行記錄,配合-i使用,tt- d -i 1000
  • -n:設置執行次數,如tt -t -n 10 demo.MathGame primeFactors
  • -l:顯示目前已存在的所有執行記錄。
  • -p:重新執行某條執行記錄,配合-i使用,如tt -i 1001 -p
  • -s:通過OGNL表達式進行查找。
  • -M:指定接收結果的字節上限,默認爲1KB
  • ---replay-times:配合-p使用,指定重新執行N次。
  • --replay-interval:執行多次時,每次執行時的間隔時間。
  • 重新執行3次某記錄,每次間隔500mstt -i 1001 -p --replay-times 3 --replay-interval 500

4.3 monitor命令

monitor:對指定的方法執行進行監控,使用參考,請參見 官方文檔

monitor | arthas (aliyun.com)

monitor 對匹配 class-patternmethod-patterncondition-express的類、方法的調用進行監控。

monitor 命令是一個非實時返回命令.

實時返回命令是輸入之後立即返回,而非實時返回的命令,則是不斷的等待目標 Java 進程返回信息,直到用戶輸入 Ctrl+C 爲止。

服務端是以任務的形式在後臺跑任務,植入的代碼隨着任務的中止而不會被執行,所以任務關閉後,不會對原有性能產生太大影響,而且原則上,任何 Arthas 命令不會引起原有業務邏輯的改變。

可選項如下:

  • -c:指定監控的週期,默認爲60s
  • -n:指定監控的週期次數。
  • 使用示例:monitor -c 10 -n 3 demo.MathGame primeFactors

4.4 stack命令

stack:輸出當前方法被調用的調用路徑。

很多時候我們都知道一個方法被執行,但這個方法被執行的路徑非常多,或者你根本就不知道這個方法是從那裏被執行了,此時你需要的是 stack 命令。

使用參考,請參見 官方文檔

stack | arthas (aliyun.com)

4.5 trace命令

trace 命令能主動搜索 class-patternmethod-pattern 對應的方法調用路徑,渲染和統計整個調用鏈路上的所有性能開銷和追蹤調用鏈路。

使用參考,請參見 官方文檔

trace | arthas (aliyun.com)

trace:方法內部調用路徑,並輸出方法路徑上的每個節點上耗時,可選項如下:

  • -i:跳過JVM的本地方法。
  • -n:和之前的-n同義。

5、OGNL表達式

rthas中的很多進階操作都需要依賴於OGNL表達式進行編寫,在線上排查時,OGNL表達式往往會結合tt、watch、monitor、stack、trace等多個命令共同使用。

arthas執行ognl表達式,獲取對應的jvm對象數據。

基本語法

ognl express -c {hashCode} --classLoaderClass {當前的全路徑 ClassLoader 信息} -x {number}

參數說明

參數名稱 參數說明
express 執行的表達式
[c:] 執行表達式的 ClassLoader 的 hashcode,默認值是 SystemClassLoader
[classLoaderClass:] 指定執行表達式的 ClassLoader 的 class name
[x] 結果對象的展開層次,默認值 1
①、調用靜態屬性

ognl '@類的全限定名@靜態屬性名'

示例:

[arthas@80573]$ ognl '@demo.MathGame@random'
②、調用靜態方法

ognl '@類的全限定名@靜態方法名("參數")'

示例1:調用入參爲基本數據類型和集合的方法:

[arthas@80573]$ ognl '@demo.MathGame@print(100,{1,2,3,4})' -x 1
null
③、調用構造方法

ognl 'new 類的全限定名()'

示例1:調用無參創建對象

[arthas@80573]$ ognl 'new java.lang.Object()'

示例2:調用有參創建對象

[arthas@80573]$ ognl 'new xxx.xx.xxx("xx",x,{1,2,3})'
④、讀取不同類型的值

示例1:讀取引用對象類型的屬性值

[arthas@80573]$ ognl '@類全限定名@方法名("參數").屬性名稱'

示例2:讀取List類型的指定元素

[arthas@80573]$ ognl '@類全限定名@方法名("參數")[下標]'

詳細的OGNL語法可參考:官方指南

Arthas線上常用場景

Arthas中集成了大部分JDK工具的功能實現,

在線上情況時,主要使用場景:

  • CPU佔用過高
  • 線程阻塞
  • 死鎖
  • 代碼動態修改
  • 方法執行緩慢
  • 排查404
  • ..................等。

1、排查CPU佔用過高問題

  • thread -n 10命令查看CPU佔用資源最高的10條線程。
  • thread命令查看線程的執行信息,定位到具體的方法。
  • monitor命令對目標方法進行監控,查看方法的調用次數與耗時。
  • ④分析monitor命令查詢出的結果,定位問題根源,確定是由於調用過於頻繁導致的,還是內部代碼邏輯問題。
  • ⑤使用jad命令反編譯class文件,根據前面分析的原因排查代碼並改善。

2、排查線程阻塞問題

  • thread篩選所有阻塞狀態的線程。
  • ②根據線程名稱定位具體的業務模塊,再選中該業務中的一條線程查看堆棧信息。
  • ③根據線程堆棧信息定位導致阻塞的具體方法,再利用stack命令查看方法堆棧信息。
  • ④利用jad工具反編譯源碼,分析業務邏輯代碼並改善。

3、排查死鎖問題

  • ①利用Arthas來檢測死鎖特別簡單,只需要執行一行命令thread -b即可。

4、排查方法執行過慢問題

  • ①通過trace命令排查方法執行速度,trace xx類 xx方法 '#cost>50ms',觀測執行時間大於50ms的該方法的調用信息。
  • ②可以結合正則表達式,同時排查多個類、多個方法,trace -E ClassA|ClassB method1|method2|method3

5、動態修改線上代碼

上線之後,發現代碼有一處小地方存在邏輯錯誤需要更改,可以直接線上修改,而不用重啓。

  • ①通過jad將要修改的類反編譯爲.java文件,輸出到指定目錄。
  • ②本地糾正.java文件後,通過mc命令重新編譯.java文件。
  • ③通過retransform命令將剛編譯的.class文件再次加載到JVM中。

總之,Arthas通過與目標應用程序交互的命令行界面,用戶可以方便地執行各種診斷和分析任務,以解決性能問題、內存泄漏等。

這種實現原理使Arthas成爲一個強大的Java診斷工具。

Arthas底層原理

Arthas是一個用於診斷和分析Java應用程序的開源工具,它的實現原理主要包括以下幾個關鍵方面:

  • Java Agent

    Arthas作爲一個Java診斷工具,通過Java Agent技術來實現對目標Java應用程序的監控和診斷。Java Agent允許Arthas以字節碼級別修改和增強目標應用程序的類,從而使其具備監控和診斷的能力。

  • Instrumentation API

    Arthas使用Java的Instrumentation API來實現Java Agent。Instrumentation API允許Arthas在目標應用程序加載類的過程中插入字節碼增強代碼,以收集信息、執行命令或修改應用程序的行爲。

  • 字節碼增強

    Arthas通過字節碼增強技術來修改目標應用程序的類。它可以在類加載期間動態地修改類的字節碼,以添加監控、日誌記錄或診斷代碼。這使得Arthas能夠捕獲應用程序的運行時信息,並執行一系列診斷和分析任務。

  • 命令行工具

    提供了一個交互式的命令行界面,用戶可以在命令行中輸入各種命令來與目標應用程序進行交互。這些命令可以查詢應用程序的狀態、分析性能問題、診斷內存泄漏等。

  • 類加載和類轉換

    Arthas在應用程序啓動時作爲Java Agent被加載,然後通過Instrumentation API監視目標應用程序的類加載過程。一旦目標應用程序加載了新的類,Arthas可以攔截類加載事件並對類進行必要的字節碼增強。

  • 類加載器隔離

    Arthas採用了一種類加載器隔離的機制,以確保Arthas的Agent類加載器與目標應用程序的類加載器相互隔離,防止衝突和干擾。

總之,Arthas的實現原理基於Java Agent、Instrumentation API和字節碼增強技術,使其能夠動態地監控、診斷和分析運行中的Java應用程序。

基於Java Agent、Instrumentation的產品,除了arthas,常用的還有pinpoint、skywalking這些非常有名氣 的產品。

關於Java Agent/Instrumentation 的知識,請參見尼恩的博客:

ByteBuddy(史上最全)

關於skywalking 的架構和源碼,請參見尼恩的視頻:

《第24章視頻:資深架構必備,徹底穿透Skywalking鏈路跟蹤源碼、JavaAgent探針技術》

參考文獻:

簡介 | arthas (aliyun.com)

說在最後: “offer自由” 很容易的

Java Agent、Instrumentation、arthas 相關的面試題,是非常常見的面試題。

以上的內容,如果大家能對答如流,如數家珍,基本上 面試官會被你 震驚到、吸引到。

最終,讓面試官愛到 “不能自已、口水直流”。offer, 也就來了。

在面試之前,建議大家系統化的刷一波 5000頁《尼恩Java面試寶典PDF》,裏邊有大量的大廠真題、面試難題、架構難題。很多小夥伴刷完後, 吊打面試官, 大廠橫着走。

在刷題過程中,如果有啥問題,大家可以來 找 40歲老架構師尼恩交流。

另外,如果沒有面試機會,可以找尼恩來改簡歷、做幫扶。

尼恩指導了大量的小夥伴上岸,前段時間,剛指導一個40歲+被裁小夥伴,拿到了一個年薪100W的offer。

狠狠卷,實現 “offer自由” 很容易的, 前段時間一個武漢的跟着尼恩捲了2年的小夥伴, 在極度嚴寒/痛苦被裁的環境下, offer拿到手軟, 實現真正的 “offer自由” !

技術自由的實現路徑:

實現你的 架構自由:

喫透8圖1模板,人人可以做架構

10Wqps評論中臺,如何架構?B站是這麼做的!!!

阿里二面:千萬級、億級數據,如何性能優化? 教科書級 答案來了

峯值21WQps、億級DAU,小遊戲《羊了個羊》是怎麼架構的?

100億級訂單怎麼調度,來一個大廠的極品方案

2個大廠 100億級 超大流量 紅包 架構方案

… 更多架構文章,正在添加中

實現你的 響應式 自由:

響應式聖經:10W字,實現Spring響應式編程自由

這是老版本 《Flux、Mono、Reactor 實戰(史上最全)

實現你的 spring cloud 自由:

Spring cloud Alibaba 學習聖經》 PDF

分庫分表 Sharding-JDBC 底層原理、核心實戰(史上最全)

一文搞定:SpringBoot、SLF4j、Log4j、Logback、Netty之間混亂關係(史上最全)

實現你的 linux 自由:

Linux命令大全:2W多字,一次實現Linux自由

實現你的 網絡 自由:

TCP協議詳解 (史上最全)

網絡三張表:ARP表, MAC表, 路由表,實現你的網絡自由!!

實現你的 分佈式鎖 自由:

Redis分佈式鎖(圖解 - 秒懂 - 史上最全)

Zookeeper 分佈式鎖 - 圖解 - 秒懂

實現你的 王者組件 自由:

隊列之王: Disruptor 原理、架構、源碼 一文穿透

緩存之王:Caffeine 源碼、架構、原理(史上最全,10W字 超級長文)

緩存之王:Caffeine 的使用(史上最全)

Java Agent 探針、字節碼增強 ByteBuddy(史上最全)

實現你的 面試題 自由:

4800頁《尼恩Java面試寶典 》 40個專題

免費獲取11個技術聖經PDF:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章