<del id="nnjnj"></del><track id="nnjnj"></track>

<p id="nnjnj"></p>

<address id="nnjnj"></address>

    <pre id="nnjnj"><pre id="nnjnj"></pre></pre>

      <noframes id="nnjnj"><ruby id="nnjnj"><ruby id="nnjnj"></ruby></ruby>

      • 自動秒收錄
      • 軟件:1973
      • 資訊:57811|
      • 收錄網站:279872|

      IT精英團

      當老板讓我從Java8升級到Java11時

      當老板讓我從Java8升級到Java11時

      瀏覽次數:
      評論次數:
      編輯: 景同
      信息來源: ITPUB
      更新日期: 2022-09-16 15:34:29
      摘要

      老板讓我把一個項目從Java8遷移到Java11,我該怎么辦呢?最簡單的辦法,當然是直接強行升級,遇到一個錯就改一個錯,別看它low,但是對于一個小型且非核心的項目來說,已經足夠了。當然,

      • 正文開始
      • 相關閱讀
      • 推薦作品

      我的老板讓我將一個項目從Java 8遷移到Java 11。我該怎么辦?

      最簡單的辦法,當然是直接升級,強制。遇到錯誤就改。別看它低,但對于一個小的非核心項目來說已經足夠了。

      當然,對于有大量代碼行的重要項目,最標準的姿勢是面對官方文檔,也就是Java 11的遷移指令文檔。

      https://docs.oracle.com/en/java/javase/11/migrate/index.html

      詳細說明了Java 8和Java 11之間可能存在的兼容性問題,并給出了一些修改措施或建議。

      理論上,如果你逐字閱讀公文,用肉眼掃描每一行代碼,可以在需要的地方進行修改,肯定能完美遷移。但人畢竟不是機器,自己寫的代碼可能有幾千行甚至上萬行,包括引入的第三方類庫。很明顯,這不是人干的事。所以,有一個神奇的工具,可以幫助我們自動掃描JDK升級時需要修改或注意的地方,直接生成可視化的HTML報告。厲害!

      它是什么

      這個工具的名字叫EMT4J,也就是Eclipse Migration Toolkit for Java。字面翻譯過來就是遷移的工具集,屬于Eclipse Foundation,是為Java準備的。官方網站地址:https://projects.eclipse.org/projects/adoptium.emt4j

      官網介紹的很貼心,直接講了一個以湯姆為主人公的小故事。大概是說湯姆要把項目從8點挪到11點,很痛苦。用了EMT4J之后,他高興得飛起來了。我很喜歡這種方式。有興趣可以看看。沒有難的詞。這個工具是阿里寫的,捐贈給了Eclipse Foundation,于是阿里云官方微信官方賬號推出了一條關于介紹它的推文,https://mp.weixin.qq.com/s/9pKGVctSd-phrV4sKqqfxA.然而,官網和推文都包含了大量的宣傳色彩和大量雜亂的信息。作為一個傻傻的開發者,我更喜歡看簡單粗暴的代碼倉庫:https://github.com/adoptium/emt4j。

      僅僅一個截圖就包含了核心功能、下載地址、快速上手體驗,這是開發者最關心的三個點。

      它怎么用

      點擊下載地址下載EMT4J后,查看其目錄結構,發現非常簡單,清晰直觀。下載streeemt4j-0.3

      emt4j-0.3

      bin

      analysis.bat

      analysis.sh

      lib

      agent

      emt4j-agent-jdk11-0.3.jar

      emt4j-agent-jdk8-0.3.jar

      analysis

      asm-9.2.jar

      commons-io-2.4.jar

      commons-lang3-3.8.jar

      emt4j-analysis-0.3.jar

      emt4j-common-0.3.jar

      ├──?gson-2.9.0.jar
      ????│???├──?lombok-1.18.8.jar
      ????│???├──?mvel2-2.4.12.Final.jar
      ????│???├──?slf4j-api-1.7.30.jar
      ????│???└──?velocity-engine-core-2.3.jar
      ????└──?maven-plugin
      ????????└──?emt4j-maven-plugin-0.3.jar
      如果只使用 javaagent 方式來分析項目,那么對于使用者來說只需要關注 agent 目錄下的兩個 jar 即可。?從 8 遷移到其他 JDK 就使用:emt4j-agent-jdk8-0.3.jar
      從 11 遷移到其他 JDK 就使用:emt4j-agent-jdk11-0.3.jar?我們寫一個簡單的 Hello World 程序,并用 JDK8 編譯。
      public?class?Hello?{
      ????public?static?void?main(?String[]?args?)?{
      ????????System.out.println(?"Hello?World!"?);
      ????}
      }
      然后對其進行 8 到 11 的遷移分析。
      java?-javaagent:emt4j-agent-jdk8-0.3.jar=to=11?Hello
      對輸出結果可視化為 HTML 格式。
      sh?analysis.sh?-o?report.html?emt4j-XXX.dat
      打開這個 HTML 文件,發現輸出的結果正符合我們預期。??對嘛,一個 Hello World 程序自然不需要考慮遷移的兼容性問題~?

      拿一個復雜的項目舉例

      ?
      我們再嘗試分析一個較為復雜的項目,依然進行剛剛那幾步動作,這回輸出的報告有點意思了。?

      ?我們就通過目錄中的摘要,就可以看到這個項目從 8 遷移到 11 所需要考慮的全部問題了。比如從 JDK 9 java.version 的 schema 發生了變化,點進去。??在如何修復那里,給出了官方說明文檔,我們繼續點進去。??簡單說就是 java.version 這個系統變量所輸出的字符串格式發生了變化,你的程序要是依賴這個字符串做截取和判斷啥的,就需要小心了。?比如報告中的問題上下文中,就給出了所有可能受之影響的方法,我們舉個例子。??在大名鼎鼎的 log4j 中的 AbstractStringLayout 類中有個 isPreJava8 方法,用來判斷是否是 Java 8 以前的版本。
      //?log4j-core:2.10.0
      private?static?boolean?isPreJava8()?{
      ????String?version?=?System.getProperty("java.version");
      ????String[]?parts?=?version.split("\\.");
      ????try?{
      ????????int?major?=?Integer.parseInt(parts[1]);
      ????????return?major?<?8;
      ????}?catch?(Exception?var3)?{
      ????????return?true;
      ????}
      }
      如果使用 Java 11 來運行這個方法,會得到 true,也就是認為 11 是 8 之前的版本,這顯然是不對的,簡單 debug 一下就知道錯在哪了。??當然,我使用的版本是 log4j-core:2.10.0,我相信大名鼎鼎的 log4j 項目一定在之后的版本修復了這個問題。?果然,在某一次 commit 上就專門修復了這個問題。??修復的方式也很 low,就是判斷第一個點前面如果是 1,就按照新的方式做判斷,即把點后面的數字作為主版本。??嗯,那看來,把這個項目從 8 升級到 11,最穩妥的方式是連這個使用老版本的 log4j 三方依賴也同時升級了。?

      什么原理

      ?
      下面探索一下這個項目的原理,GitHub 官網中給出了一張架構圖。??左邊是 agent 方式分析運行中的項目,上面是分析靜態的 Jar 和 Class 文件等,他們僅僅是解析符號時有所不同。?中間部分是,當符號解析完畢后,都需要讀取規則 Rules,這些規則 Rules 就是判斷是否會出現兼容性問題的邏輯,如果匹配到了,則記錄下來。?右下方是,把剛剛記錄下來的兼容性問題,用更友好的方式比如 HTML 的形式輸出,給最終的用戶看。?所以整個架構還是十分清晰的,重點是里面的細節是如何處理的,我這里只說關鍵的環節。?agent 方式分析可能不太直觀,如果你想了解,可以從這個標準 javaagent 項目的 premain 方法開始看起。??我這里正好了解一下另一種直接靜態掃描 class 文件或 jar 文件的檢查方式,這個就很直觀了。?首先我們故意寫一個可以觸發上面說的 java.version 格式兼容性問題的代碼。
      class?Hello?{
      ????public?static?void?main(String[]?var0)?{
      ????????System.out.println("hello");
      ????????System.out.println(System.getProperty("java.version"));
      ????}
      }
      然后把它編譯成 class 文件,放入一個 classFiles 文件夾中,作為我們的掃描文件夾。?然后執行 sh 命令,表示檢查該文件夾中 8 遷移到 11 的風險項。
      sh?analysis.sh?-f?8?-t?11?-o?report.html?classFiles
      這個 sh 腳本其實就是執行 AnalysisMain 的主方法,并且將上面幾個參數作為 args 傳入進去。
      //?org/eclipse/emt4j/analysis/AnalysisMain.java
      public?class?AnalysisMain?{?
      ????public?static?void?main(String[]?args)?throws?IOException,?ClassNotFoundException,?InterruptedException,?URISyntaxException?{
      ????????...
      ????????ReportConfig?config?=?doAnalysis(args,?...);
      ????????doReport(config,?...);
      ????}
      ????...
      }
      所以從這個入口開始看起就好了。?主方法的結構也很簡單,doAnalysis 就是對這些 class 文件進行分析,得出結果。doReport 就是將分析結果可視化,比如生成 HTML 文件。?具體調用鏈我不一一展開,只看很關鍵的環節。首先 ClassAnalyzer 中的 processClass 方法使用了 ASM 將 class 文件解析為各種符號,保存在 ClassSymbol 對象里。
      //?org/eclipse/emt4j/analysis/analyzer/ClassAnalyzer.java
      protected?static?void?processClass(byte[]?classFileContent?...)?{
      ????ClassSymbol?symbol?=?ClassInspectorInstance.getInstance().getSymbolInClass(classFileContent);
      ????...
      }
      然后,由各種規則文件利用這些符號信息做判斷,比如 WholeClassRule,表示需要整個 class 文件信息才能做判斷的規則。
      @RuleImpl(type?=?"whole-class")
      public?class?WholeClassRule?extends?ExecutableRule?{
      ????...
      ????@Override
      ????protected?CheckResult?check(Dependency?dependency)?{
      ????????Map<String,?Object>?mvelMap?=?new?HashMap<>();
      ????????mvelMap.put("typeSet",?dependency.getClassSymbol().getTypeSet());
      ????????mvelMap.put("methodSet",?toMethodIdentifierSet(dependency.getClassSymbol().getCallMethodSet()));
      ????????mvelMap.put("cpSet",?dependency.getClassSymbol().getConstantPoolSet());
      ????????Object?result?=?MVEL.eval(mvel2Rule,?mvelMap);
      ????????if?(result?instanceof?Boolean)?{
      ????????????return?((Boolean)?result)???CheckResult.FAIL?:?CheckResult.PASS;
      ????????}?else?{
      ????????????throw?new?JdkMigrationException("Mvel2?rule?file"?+?mvel2RuleFile?+?"?must?return?a?boolean?result!Now?result?type?is?:?"?+?result.getClass());
      ????????}
      ????}
      }
      這里將剛剛的符號信息取出來,放入 mvelMap 中,分別是 typeSet 類型集合、methodSet 方法集合、cpSet 常量池集合。?接下來使用 MVEL 這個第三方類庫進行判斷,這是一個可以使用表達式進行匹配判斷的工具類,很方便,規則表達式就寫在這個 mvel2Rule 里。?這個 mvel2Rule 有很多,其中檢查 java.version 這個兼容性問題的表達式寫在下面這個文件里。
      //?emt4j-common/src/main/resources/default/rule/8to11/data/mvel2-rule-getjavaversion.cfg
      methodSet.contains('java.lang.System.getProperty')?&&?
      (
      ??cpSet.contains('java.version')?||?
      ??cpSet.contains('java.specification.version')?||?
      ??cpSet.contains('java.runtime.version')
      )
      這個規則表達式很好理解,你不用了解它的寫法也能看懂,就是當使用了?System.getProperty方法,并且字符串常量池中有java.version 或 java.specification.version 或 java.runtime.version時,就視作有兼容性問題。?可以看出,這個判斷非常粗糙,就是簡單的字符串包含判斷而已,由此可見,兼容性問題的判斷,也逃脫不了這種方式,不要以為里面利用了什么智能分析方法。?當這個兼容性問題被記錄下來后,最終輸出 HTML 文件的時候,會通過 ResourceBundle 查看官方文檔說明,將詳細信息寫入 HTML 文件中。??最終就看到了效果,就是這么簡單。??

      再說兩句

      ?
      通過體驗和了解這個項目,我們可以學到很多東西,麻雀雖小,五臟俱全。?首先它通過 agent 和 sh 兩種方式提供給用戶使用,但中間的分析判斷邏輯都是共用的。?然后,這個項目使用了專門解析 class 文件的 ASM 工具,把符號信息提取出來方便后面使用。??又使用了 MVEL 作為規則判斷的工具,使得規則判斷只需要寫好表達式即可。??最后輸出為 HTML 時,為了查詢對應兼容性問題對應的官方說明,使用了 ResourceBundle 查找官方文檔說明,由此我們可以繼續深入,了解下官方文檔的查詢規范,而且是從代碼層面的,十分嚴謹。??好的工具就是利用了這么多知名的工具,使自己便利。那我們也可以利用這個項目,做些自己的事情。?比如你做的某款工具,甚至你定制的某款 JDK,需要檢查業務代碼中是否有兼容性問題,或者你就單純想掃描下業務代碼中是否有什么什么你關心的東西,那么你可以僅僅修改這個項目中的各種規則表達式,并且定制化自己的 HTML 報告格式即可出色完成這個功能。?其它的,如何掃描 class,如何解析 class 符號,如何調用規則進行判斷,如何輸出渲染 HTML,都不用再自己做了。?我最近就想用它做點事情,等做好了,后面再給大家分享,今天就到這里吧~
      ------
      以后這個號不接任何廣告,除非是我真心想推薦的,以后正常文章也不開賞贊,我會在每個月的第一個星期二開,并且留言區和大家一塊熱鬧熱鬧,要記得來喲~
      標簽:項目 文件 方式
      平均負載和CPU利用率有什么區別?
      ? 上一篇 2022-09-16
      長文解讀春季交易!隔離?傳播性?網被消滅了!
      下一篇 ? 2022-09-16
      • 如何在Ubuntu中保留文件系統并備份當前開發板鏡像
        0閱讀 0條評論 個贊
        在Ubuntu保留文件系統或者說備份當前開發板鏡像的需求在不斷增加。比如Ubuntu文件系統需要安裝庫文件的話直接使用apt-get工具就可以下載,但由于需要下載的核心板較多,比較費時間,這時需要將安……
      • 國產核心板全志T507助力消防系統升級
        0閱讀 0條評論 個贊
        9月16日下午,位于湖南長沙市區內的中國電信大樓發生火災,建筑高度218米,現場濃煙滾滾,數十層樓體燃燒劇烈。消防救援人員趕到現場后很快將火勢控制住,目前大樓火勢已被撲滅,所幸未發現人員傷亡。湖南電信……
      • 教大家如何處理Spring Boot易流中的用戶和群體!
        0閱讀 0條評論 個贊
        1.準備工作2.用戶操作2.1添加用戶2.2修改用戶2.3刪除用戶2.4查詢用戶3.組操作3.1添加組3.2修改組3.3刪除組3.4查詢組4.查看表詳情雖然說我們在實際開發中,……
      • 從PG15開始WAL壓縮優化
        0閱讀 0條評論 個贊
        PG15傳聞中的超級令人激動的功能大多數跳票了,年初我也寫過一個關于PG15新功能跳票的文章。PG15BETA已經發出幾個月了,似乎PG15里令人激動人心的功能不多,不過從長長的新功能列表里,……
      • 深入了解美團葉子發射器開源方案
        0閱讀 0條評論 個贊
        大家好,我是樹哥。之前我們有聊過「如何設計一個分布式ID發號器」,其中有講過4種解決方案,分別是:UUID類雪花算法數據庫自增主鍵Redis原子自增美團以第2、3種解決方案為基礎,開發出……
      發表評論 共有條評論
      用戶名: 密碼:
      驗證碼: 匿名發表
      • 國產核心板全志T507助力消防系統升級
        0閱讀 0條評論 個贊
        9月16日下午,位于湖南長沙市區內的中國電信大樓發生火災,建筑高度218米,現場濃煙滾滾,數十層樓體燃燒劇烈。消防救援人員趕到現場后很快將火勢控制住,目前大樓火勢已被撲滅,所幸未發現人員傷亡。湖南電信……
      • 深入了解春季交易:介紹 使用 原則
        8閱讀 0條評論 個贊
        大家好,我是樹哥。Spring事務是復雜一致性業務必備的知識點,掌握好Spring事務可以讓我們寫出更好地代碼。這篇文章我們將介紹Spring事務的誕生背景,從而讓我們可以更清晰地了解Sp……
      • 人人都能讀懂的源代碼——那些關于DOM的常見鉤子包(二)
        0閱讀 0條評論 個贊
        本文是深入淺出ahooks源碼系列文章的第十五篇,該系列已整理成文檔-地址。覺得還不錯,給個star支持一下哈,Thanks。本篇接著針對關于DOM的各個Hook封裝進行解讀。useFul……
      • 一個沒有寫代碼的案例 讓我們看看Flowable為我們提供了哪些功能
        3閱讀 0條評論 個贊
        其實松哥之前已經寫過文章和大家介紹了flowable-ui的玩法了,這是官方提供的一個工具,這個工具不僅可以用來繪制流程圖,還可以用來部署一個流程應用,通過這個流程應用我們可以體驗一把flowa……
      • 基于ASP.NET核心6.0的簡潔架構
        0閱讀 0條評論 個贊
        背景最近嘗試錄制了一個系列視頻:《ASP.NETCore6.0+Vue.js3實戰開發》,本節是視頻內部整潔架構的理論和實戰的文字稿。因為在錄制之前,我通常會編寫完整的文字內容作為視頻文案,這……
      • SQL Server聯接方式
        0閱讀 0條評論 個贊
        0.參考文獻MicrosoftSQLServer企業級平臺管理實踐看懂SqlServer查詢計劃1.測試數據準備參考:SqlServer中的表訪問方式TableScan,IndexScan……
      • 內存泄漏——原因、避免和位置
        0閱讀 0條評論 個贊
        .css-1yuhvjn{margin-top:16px;}.css-3jt6os.FileLinkCard{-webkit-align-items:center;-webkit-box-align……
      • 如何使用helm優雅地安裝prometheus-operator并監控k8s集群微服務
        0閱讀 0條評論 個贊
        前言:隨著云原生概念盛行,對于容器、服務、節點以及集群的監控變得越來越重要。Prometheus作為Kubernetes監控的事實標準,有著強大的功能和良好的生態。但是它不支持分布式,不支持數據……
      • 解決ShardingJdbc不支持復雜SQL問題的說明
        18閱讀 0條評論 個贊
        背景介紹公司最近做分庫分表業務,接入了ShardingJDBC,接入完成后,回歸測試時發現好幾個SQL執行報錯,關鍵這幾個表都還不是分片表。報錯如下:這下糟了嘛。熟悉ShardingJDB……
      • 珊瑚??缃K端解決方案及移動端動態布局實踐
        0閱讀 0條評論 個贊
        目錄1.背景和介紹1.1跨端動態化技術的現狀和問題1.2珊瑚海介紹1.3與其他框架的對比1.4應用案例2.珊瑚海技術方案2.1整體設計2.2D2X2.3開發工具2.4移動端引擎2.5……
      • 圖解架構| SaaS、PaaS、IaaS
        0閱讀 0條評論 個贊
        這是悟空的第164篇原創文章官網:www.passjava.cn你好,我是悟空哥。上次聊到了架構圖如何畫,其中涉及到了云服務的架構圖,里面提到了很重要的三個概念PaaS、IaaS、SaaS,很有必要……
      • 數據庫發展史II-數據倉庫
        6閱讀 0條評論 個贊
        回顧數據倉庫的發展歷程,大致可以將其分為幾個階段:萌芽探索到全企業集成時代、企業數據集成時代、混亂時代--"數據倉庫之父"間的論戰、理論模型確認時代以及數據倉庫產品百家爭鳴時代。數據倉庫理論發展歷程上……
      • 面試問題:Java序列化和反序列化
        0閱讀 0條評論 個贊
        目錄序列化和反序列化的概念應用場景?序列化實現的方式繼承Serializable接口,普通序列化繼承Externalizable接口,強制自定義序列化serialVersionUID的作用靜態變量不會……
      • 基于位置變化的市縣彈出引導切換
        31閱讀 0條評論 個贊
        目錄1.背景2.模型方案產出3.總結01背景58App業務中有城市和縣域兩個首頁,兩者中間有一個過渡選擇頁,用戶通過點擊該頁面下的條目內容可以切換到對應條目的首頁;比如:點擊“北京”會跳轉到北京(市)……
      • 記錄一次數據庫滿CPU的故障排除過程
        0閱讀 0條評論 個贊
        1前言近期隨著數據量的增長,數據庫CPU使用率100%報警頻繁起來。第一個想到的就是慢Sql,我們對未合理運用索引的表加入索引后,問題依然沒有得到解決,深入排查時,發現在orderbyida……
      • Linux環境程序如何運行?
        0閱讀 0條評論 個贊
        .css-1yuhvjn{margin-top:16px;}.css-3jt6os.FileLinkCard{-webkit-align-items:center;-webkit-box-align……
      • 關于這個能見度的例子 網上95%的文章都是錯的!
        0閱讀 0條評論 個贊
        你好,我是坤哥上周我在查閱資料時無意中搜到一篇解釋volatile用法的博文,這篇博文排得很靠前,不過很遺憾,雖然結論是對的,但分析過程完全錯誤,而且我發現網上很多文章都用這個例子來解釋vola……
      • SQL Server數據庫性能優化
        0閱讀 0條評論 個贊
        分析比較執行時間計劃讀取情況1.查看執行時間和cpusetstatisticstimeonselect*fromBus_DevHistoryDatasetstatisticstime……
      • 基于 網絡6的輕量級Webapi框架緊固點
        0閱讀 0條評論 個贊
        大家好,我是等天黑。FastEndpoints是一個基于.NET6開發的開源webapi框架,它可以很好地替代.NETMinimalAPIs和MVC,專門為開發效率而生,帶來了全……
      • [設計模式] Java設計模式-橋模式
        0閱讀 0條評論 個贊
        目錄【設計模式】Java設計模式-橋接模式簡介橋接模式實例代碼示例①、品牌接口②、汽車品牌③、抽象汽車類④、汽車類型子類⑤、橋接模式測試1|1簡介橋接(Bridge)是用于把抽象化與實現化解耦,使……
      最近發布資訊
      更多
      警花高潮嗷嗷叫
      <del id="nnjnj"></del><track id="nnjnj"></track>

      <p id="nnjnj"></p>

      <address id="nnjnj"></address>

        <pre id="nnjnj"><pre id="nnjnj"></pre></pre>

          <noframes id="nnjnj"><ruby id="nnjnj"><ruby id="nnjnj"></ruby></ruby>