你還搞不懂Java如何實現熱更新?這樣解釋你應該能看懂了吧?

来源:https://www.cnblogs.com/java-xiatian/archive/2020/06/19/13166424.html
-Advertisement-
Play Games

Arthas(阿爾薩斯)是 Alibaba 開源的一款 Java 診斷工具,使用它我們可以監控和排查 Java 程式,然而它還提供了非常實用的 Java 熱更新功能。 所謂的 Java 熱更新是指在不重啟項目的情況下實現代碼的更新與替換。使用它可以實現不停機更新 Java 程式,尤其是對那些啟動非... ...


你還搞不懂Java如何實現熱更新?這樣解釋你應該能看懂了吧?

 

你還搞不懂Java如何實現熱更新?這樣解釋你應該能看懂了吧?

 

你還搞不懂Java如何實現熱更新?這樣解釋你應該能看懂了吧?

 

你還搞不懂Java如何實現熱更新?這樣解釋你應該能看懂了吧?

 

你還搞不懂Java如何實現熱更新?這樣解釋你應該能看懂了吧?

 

你還搞不懂Java如何實現熱更新?這樣解釋你應該能看懂了吧?

 

Arthas(阿爾薩斯)是 Alibaba 開源的一款 Java 診斷工具,使用它我們可以監控和排查 Java 程式,然而它還提供了非常實用的 Java 熱更新功能。

所謂的 Java 熱更新是指在不重啟項目的情況下實現代碼的更新與替換。使用它可以實現不停機更新 Java 程式,尤其是對那些啟動非常耗時的 Java 項目來說,更是效果顯著。

Arthas 的使用其實非常簡單,它為我們提供了一個 Jar 包,我們只需要把這個 Jar 下載到本地,然後運行這個 Jar 包就可以正常使用它的功能了。

Arthas 功能簡述

當你遇到以下類似問題而束手無策時,Arthas 可以幫助你解決(來自官方):

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

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

Arthas 使用

Arthas 的使用步驟如下。

步驟一:下載 Arthas

首先,我們先把 Arthas 的 Jar 包下載到本地,它的下載地址是:
https://alibaba.github.io/arthas/arthas-boot.jar

步驟二:啟動 Arthas

我們只需要使用普通的 jar 包啟動命令:java -jar arthas-boot.jar 來啟動 Arthas 即可,啟動成功之後的運行界面如下:

你還搞不懂Java如何實現熱更新?這樣解釋你應該能看懂了吧?

 

如上圖所示則表示 Arthas 啟動成功。

小貼士:當我們運行 java -jar arthas-boot.jar 命令時,首先需要先切換目錄至該 jar 包的位置,才能正常的啟動 Arthas。

步驟三:運行 Arthas

當我們啟動完 Arthas 之後,根據上圖的提示,我們需要選擇一個要調試的 Java 進程,例如我們輸入“4”來監測我自己寫的一個 Java 測試程式,執行結果如下:

你還搞不懂Java如何實現熱更新?這樣解釋你應該能看懂了吧?

 

當出現 Arthas 的 logo 之後,表示 Arthas 正常載入了 Java 進程。

步驟四:操作 Arthas

當 Arthas 載入 Java 進程成功之後,我們就可以輸入相關的命令來查看相關的信息了。

假如我們把本地環境視為生產伺服器,我們此時需要查看某個運行的 Java 程式是否為最新版的。

在沒有 Arthas 之前,我們通常的步驟是這樣的:

  1. 找到相應的 jar 包(或者 war 包);
  2. 將 jar 包(或者 war 包)下載到本地;
  3. 找出相應的類進行解壓操作;
  4. 然後將解壓的 class 文件拖拽到 Java 編譯器(Idea 或 Eclipse)中,查看是否為最新的代碼。

但如果使用的是 Arthas,那麼我們就可以直接通過反編譯命令,將位元組碼編譯為正常的 Java 代碼,然後再確認是否為最新的代碼即可。我們只需要執行 jad 命令即可,實現示例如下:

你還搞不懂Java如何實現熱更新?這樣解釋你應該能看懂了吧?

 

這樣我們就可以直接來查看這個發佈的程式是否為最新版本了。

不僅如此,我們還可以使用 Arthas 來監測整個程式的運行情況,如下圖所示:

你還搞不懂Java如何實現熱更新?這樣解釋你應該能看懂了吧?

 

我們還可以用 Arthas 來查看一些 JVM 的相關信息,如下圖所示:

你還搞不懂Java如何實現熱更新?這樣解釋你應該能看懂了吧?

 

更多 Arthas 的功能,請訪問:
https://alibaba.github.io/arthas/commands.html

熱更新 Java 代碼

你還搞不懂Java如何實現熱更新?這樣解釋你應該能看懂了吧?

 

你還搞不懂Java如何實現熱更新?這樣解釋你應該能看懂了吧?

 

假如我們原來的代碼是這樣的:

package com.example;

import java.util.concurrent.TimeUnit;

public class App {
    public static void main(String[] args) throws InterruptedException {
        while (true) { // 每兩秒鐘列印一條信息
            TimeUnit.SECONDS.sleep(3);
            sayHi();
        }
    }

    private static void sayHi() {
        // 需要修改的標識
        boolean flag = true;
        if (flag) {
            System.out.println("Hello,Java.");
        } else {
            System.out.println("Hello,Java中文社群.");
        }
    }
}

 

我們現在想要把 flag 變數改為 false 就可以這樣來做:

  1. 使用 Arthas 的記憶體編譯工具將新的 Java 代碼編譯為位元組碼;
  2. 使用 Arthas 的 redefine 命令實現熱更新。

1.編譯位元組碼

首先,我們需要將新的 Java 代碼編譯為位元組碼,我們可以通過 Arthas 提供的 mc 命令實現,mc 是 Memory Compiler(記憶體編譯器)的縮寫。

實現示例如下:

[arthas@3478]$ mc /Users/admin/Desktop/App.java -d /Users/admin/Desktop
Memory compiler output:
/Users/admin/Desktop/com/example/App.class
Affect(row-cnt:1) cost in 390 ms.

 

其中 -d 表示編譯文件的存放位置。

小貼士:我們也可以使用 javac App.java 生成的位元組碼,它與此步驟執行的結果相同。

2.執行熱更新

有了位元組碼文件之後,我們就可以使用 redefine 命令來實現熱更新了,實現示例如下:

[arthas@51787]$ redefine /Users/admin/Desktop/com/example/App.class
redefine success, size: 1

 

從上述結果可以看出,熱更新執行成功,此時我們去控制台查看執行結果,如下圖所示:

你還搞不懂Java如何實現熱更新?這樣解釋你應該能看懂了吧?

 

這說明熱更新執行確實成功了。

Arthas 熱更新註意事項

使用熱更新功能有一些條件限制,我們只能用它來修改方法內部的一些業務代碼,如果我們出現了以下任意一種情況,那麼熱更新就會執行失敗:

  1. 增加類屬性(類欄位);
  2. 增加或刪除方法;
  3. 替換正在運行的方法。

最後一條我們需要單獨說明一下,假如我們把上面的示例改為如下代碼:

package com.example;

import java.util.concurrent.TimeUnit;

public class App {
    public static void main(String[] args) throws InterruptedException {
        while (true) { // 每兩秒鐘列印一條信息
            TimeUnit.SECONDS.sleep(3);
            boolean flag = true;
            if (flag) {
                System.out.println("Hello,Java.");
            } else {
                System.out.println("Hello,Java中文社群.");
            }
        }
    }
}

 

那麼此時我們再進行熱更新操作修改 flag 的值,那麼就會執行失敗,因為我們替換的是正在運行中的方法,而我們正常示例中的代碼之所以能成功,是因為我們在 while無線迴圈中調用了另一個方法,而那個方法是被間歇性使用的,因此可以替換成功。

總結

本文我們講了 Arthas 的概念以及具體的使用流程,Arthas 其實就是一個普通的 Java 程式,我們可以使用 java -jar arthas-boot.jar 來啟動它,然後再選擇我們要操作的 Java 進程,這樣就可以實現狀態監控和其他操作。

文章的後半部分,我們介紹了 Arthas 的熱更新功能,而熱更新本質上只需要使用一個 redefine 命令來載入新的位元組碼文件就可以實現熱更新了,但需要註意熱更新不能替換正在運行的方法,它只能修改方法內部的業務代碼,如果修改了類欄位或者是更改了類方法,那麼熱更新就會執行失敗。

分享

最後小編整理了一份Java相關的資料,需要的小伙伴可以加我微信即可免費領取!

放一些大概截圖,感興趣的小伙伴可以收著。

你還搞不懂Java如何實現熱更新?這樣解釋你應該能看懂了吧?

java面試題及大廠真題

你還搞不懂Java如何實現熱更新?這樣解釋你應該能看懂了吧?

大量電子書

知識點相關面試題

你還搞不懂Java如何實現熱更新?這樣解釋你應該能看懂了吧?

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 函數進階 遞歸函數 定義一個函數在函數的內部調用自身,如果不設置遞歸邊界,將死迴圈無限調用知道被pycharm等ide觀測到拋出異常終止 案例1: def fun(): if n == 0: return n else: return n*fun(n-1) # 在當前函數中,就是當n=0的時候停止調 ...
  • 很多小伙伴在自己寫代碼的時候,已經多次使用過#include命令。使用庫函數之前,應該用#include引入對應的頭文件。其實這種以#號開頭的命令稱為預處理命令。 C語言源文件要經過編譯、鏈接才能生成可執行程式: 1) 編譯(Compile)會將源文件(.c文件)轉換為目標文件。對於 VC/VS,目 ...
  • 生成migration文件 1 php artisan make:migration alter_xxx_table 修改migration文件 1 public function up() 2 { 3 Schema::table('xxx', function (Blueprint $table) ...
  • 最近身邊朋友換工作、轉型的越來越多。爬到一定高度,或者說到了一定年齡,每個選擇都顯得尤為重要。不僅因為高昂的機會成本,還有大家對後續規劃的多重考慮。有一個說法你可能聽過:混職場,要擁有不可替代的能力。很多人以為,這是指一個人必須有一項特別厲害的技能,秒殺99.9%的那種。不然怎麼叫不可替代呀?但我並 ...
  • toUpperCase:toUpperCase() 方法將字元串小寫字元轉換為大寫。示例: String Str = new String("www.runoob.com"); System.out.print("返回值 :" ); System.out.println( Str.toUpperCa ...
  • Reactor Reactor 項目的主要 artifact 是 reactor-core,這是一個基於 Java 8 的實現了響應式流規範的響應式庫。 Reactor 提供了實現 Publisher 的響應式類 Flux 和 Mono,以及豐富的操作符。一個 Flux 代表 0...N 個元素的響 ...
  • import pickle d1={'a':234,'b':[3,5,7],'w':[4,5]} #存儲數據 f=open(r'D:\matplotlib繪圖\aaa.pickle','wb') pickle.dump(d1,f) f.close() #讀取數據 with open(r'D:\mat ...
  • ​ 歡迎將公眾號【程式員書單】公眾號置頂,技術乾貨第一時間送達! 本公眾號專註於IT技術,致力於為程式員推薦好書。作者黃小斜是非科班出身的程式員,在自學編程的路上讀過很多書,踩過很多坑,現在在阿裡做研發,一直認為讀書是程式員必不可少的好習慣之一。 程式員不止需要閱讀技術書籍,更需要閱讀更多其他領域的 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...