如何閱讀jdk源碼?

来源:https://www.cnblogs.com/tong-yuan/archive/2019/04/07/10667870.html
-Advertisement-
Play Games

如何閱讀jdk源碼? 1. 設定目標 2. 提出問題 3. 如何提出問題 4. 帶著問題閱讀源碼,忽略不必要的細節,死磕重要的細節 5. 多做比較 6. 多做實驗 7. 耐心&堅持 8. 彩蛋 ...


簡介

這篇文章主要講述jdk本身的源碼該如何閱讀,關於各種框架的源碼閱讀我們後面再一起探討。

筆者認為閱讀源碼主要包括下麵幾個步驟。

設定目標

凡事皆有目的,閱讀源碼也是一樣。

從大的方面來說,我們閱讀源碼的目的是為了提升自己的技術能力,運用到工作中,遇到問題快速定位,升職加薪等等。

從小的方面來說,閱讀某一段源碼的目的就是要搞清楚它的原理,就是死磕,就是那種探索真相的固執。

目的是抽象的,目標是具體的,我們閱讀源碼之前一定要給自己設定一個目標。

比如,下一章我們將要一起學習的ConcurrentHashMap,我們可以設定以下目標:

(1)熟悉ConcurrentHashMap的存儲結構;

(2)熟悉ConcurrentHashMap中主要方法的實現過程;

(3)探索ConcurrentHashMap中出現的新技術;

提出問題

有了目標之後,我們要試著提出一些問題。

還是以ConcurrentHashMap為例,筆者提出了以下這些問題:

(1)ConcurrentHashMap與HashMap的數據結構是否一樣?

(2)HashMap在多線程環境下何時會出現併發安全問題?

(3)ConcurrentHashMap是怎麼解決併發安全問題的?

(4)ConcurrentHashMap使用了哪些鎖?

(5)ConcurrentHashMap的擴容是怎麼進行的?

(6)ConcurrentHashMap是否是強一致性的?

(7)ConcurrentHashMap不能解決哪些問題?

(8)ConcurrentHashMap除了併發安全,還有哪些與HashMap不同的地方,為什麼要那麼實現?

(8)ConcurrentHashMap中有哪些不常見的技術值得學習?

如何提出問題

很多人會說,我也知道要提出問題,但是該怎麼提出問題呢?

這確實是很困難的一件事,筆者認為主要是三點:

(1)問自己

把自己當成面試官問自己,往死里問的那種。

如果問自己問不出幾個問題,也不要緊,請看下麵。

(2)問互聯網

很多問題可能自己也想不到,那就需要上網大概查一下相關的博客,看人家有沒有提出什麼問題。

或者,查詢相關面試題。

比如,筆者學習ConcurrentHashMap這個類時,上網一查很多都是基於jdk7的,那這時候就可以提出一個問題,jdk8與jdk7中ConcurrentHashMap這個類的實現方式有何不同?jdk8對jdk7作了哪些優化?

(3)不斷發現問題

在源碼閱讀的過程中,可能看著看著就遇到個問題,這是非常常見的,這種問題也應該保留下來研究研究。

比如,ConcurrentHashMap中size()方法是怎麼實現的?@sun.misc.Contended這玩意是什麼鬼東西?然後上網一查,與是為了避免偽共用,我X,偽共用又是啥?然後你再查一下偽共用,又出來了CPU多級緩存?學完CPU多級緩存,是不是覺得跟jvm的記憶體模型很像?問完這一連串問題,是不是感覺世界都清晰了?^_^

看吧,問題是源源不斷地被髮現的。

所以,一開始提不出幾個問題也不要緊,關鍵是要看,看了才能發現更多的問題。

帶著問題閱讀源碼,忽略不必要的細節,死磕重要的細節

首先,一定要帶著問題閱讀源碼。

其次,一定要忽略不必要的細節。

再次,一定要死磕重要的細節。

乍一看,後面兩步似乎有所矛盾,其實不然,忽略不必要的細節是為了不迷失在源碼的世界中,死磕重要的細節是為了弄清楚源碼的真相。

這裡的細節是忽略還是死磕,主要是看跟問題的相關性。

jdk源碼還是比較好閱讀的,如果後面看spring的源碼,做不到忽略不必要的細節,真的是會迷失的,先埋個伏筆哈~~

舉個例子,之前閱讀過ArrayList的序列化相關的代碼中的readObject()方法。

s.readInt();這行是幹嘛的?省略行不行?這時候就要去瞭解序列化相關的知識,然後看看writeObject()裡面的實現,這就是要死磕的代碼。

SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, capacity);這行又是幹嘛的?乍一看,好像是跟許可權相關的代碼,跟我們的問題“序列化”無關,忽略之,如果實在想知道,先打個標記,等把序列化的問題解決了再來研究這個東西。

private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
    // 聲明為空數組
    elementData = EMPTY_ELEMENTDATA;

    // 讀入非transient非static屬性(會讀取size屬性)
    s.defaultReadObject();

    // 讀入元素個數,沒什麼用,只是因為寫出的時候寫了size屬性,讀的時候也要按順序來讀
    s.readInt();

    if (size > 0) {
        // 計算容量
        int capacity = calculateCapacity(elementData, size);
        SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, capacity);
        // 檢查是否需要擴容
        ensureCapacityInternal(size);
        
        Object[] a = elementData;
        // 依次讀取元素到數組中
        for (int i=0; i<size; i++) {
            a[i] = s.readObject();
        }
    }
}

多做比較

在閱讀jdk源碼的時候,還有很重要的一點,就是要多做比較,比較也可以分為橫向比較和縱向比較。

(1)橫向比較

就是與相似的類做比較。比如,集合模塊中,基本都是各種插入、查詢、刪除元素,那這時候可以從數據結構、時間複雜度等維度進行比較,這就是橫向比較。

(2)縱向比較

可以從集合發展的歷史進行比較。比如,HashMap的發展史,從(單個數組)實現(沒錯,可以直接用一個數組實現HashMap),到(多數組+鏈表)實現,再到jdk8中的(多數組+鏈表+紅黑樹)實現,這就是縱向比較。

多做實驗

最後一步,最最最最重要的就是要多做實驗。

比如,ConcurrentHashMap是不是強一致性的?

可以啟動多個線程去不斷調用get()、put()、size()方法,看看是不是強一致性的。

耐心&堅持

這一點我不多說,大家都懂得。

不管是什麼領域,耐心&堅持都是最難能可貴的品質。

閱讀源碼也是一樣,只要耐心地堅持下去,終將有所收穫。

彩蛋

哎呀,一不小心透露了下一章ConcurrentHashMap的內容。

大家可以用本篇所說的方法試著閱讀一下ConcurrentHashMap的源碼,下一章我們再一起學習哈哈~~


qrcode


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

-Advertisement-
Play Games
更多相關文章
  • 1.上傳視頻信息的jsp頁面uploadVideo.jsp <body background="image/bk_hero.jpg"><div id="upld" style="height:300px;width:300px;margin-left: 300px;margin-top: 100px ...
  • 後臺servlet設置 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String method=reque ...
  • 清明節和朋友去被抖音帶火的一個餐廳,下午兩點鐘取晚上的號,前面已經有十幾桌了,四點半餐廳開始正式營業,等輪到我們已經近八點了。餐廳分為幾個區域,只有最火的區域(在小船上)需要排號,其他區域基本上是隨到隨吃的,最冷清的區域幾乎都沒什麼人。菜的價格異常的貴,味道也並不好。最後送出兩張圖: 好了,進入今天 ...
  • 簡介 當你的程式不能正常運行的時候,Python會在控制台列印一段提醒,告訴你一個錯誤,這個錯誤就是異常。 錯誤 我在控制台寫了一段無效的代碼,將print()的括弧去掉,在執行這條語句的時候,系統提示語法錯誤,無效的語句(我百度翻譯的)。這就是錯誤處理器所作的工作。 再換一種方式寫錯誤: 在程式獲 ...
  • 1.防止用戶沒有登錄即可訪問其他頁面 1.1>從session中判斷用戶是否登陸 ServletActionContext.getRequest().getSession();以此為依據是否放行 2.註冊自定義攔截器 3.設置預設攔截器 ...
  • 1>***貓: python基礎類: 技能類: 業務類: 你對電商的業務瞭解嗎? 我問你一個具體的電商的業務啊:電商在大多數領域中都是有庫存的,我在下訂單的時候,我的庫存的變化,你知道嗎?(我問的是你怎麼去處理庫存的變化?)因為客戶下單的時候,有些是去減庫存了,有些不減對吧?你的理解呢? 你事務的時 ...
  • 什麼是多線程 利用對象,可將一個程式分割成相互獨立的區域。我們通常也需要將一個程式轉換成多個獨立運行的子任 務。象這樣的每個子任務都叫作一個“線程”(Thread)。編寫程式時,可將每個線程都想象成獨立運行,而且 都有自己的專用CPU。一些基礎機制實際會為我們自動分割CPU的時間。我們通常不必關心這 ...
  • Fibonacci again and again(http://acm.hdu.edu.cn/showproblem.php?pid=1848) Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Oth ...
一周排行
    -Advertisement-
    Play Games
  • 前言 本文介紹一款使用 C# 與 WPF 開發的音頻播放器,其界面簡潔大方,操作體驗流暢。該播放器支持多種音頻格式(如 MP4、WMA、OGG、FLAC 等),並具備標記、實時歌詞顯示等功能。 另外,還支持換膚及多語言(中英文)切換。核心音頻處理採用 FFmpeg 組件,獲得了廣泛認可,目前 Git ...
  • OAuth2.0授權驗證-gitee授權碼模式 本文主要介紹如何筆者自己是如何使用gitee提供的OAuth2.0協議完成授權驗證並登錄到自己的系統,完整模式如圖 1、創建應用 打開gitee個人中心->第三方應用->創建應用 創建應用後在我的應用界面,查看已創建應用的Client ID和Clien ...
  • 解決了這個問題:《winForm下,fastReport.net 從.net framework 升級到.net5遇到的錯誤“Operation is not supported on this platform.”》 本文內容轉載自:https://www.fcnsoft.com/Home/Sho ...
  • 國內文章 WPF 從裸 Win 32 的 WM_Pointer 消息獲取觸摸點繪製筆跡 https://www.cnblogs.com/lindexi/p/18390983 本文將告訴大家如何在 WPF 裡面,接收裸 Win 32 的 WM_Pointer 消息,從消息裡面獲取觸摸點信息,使用觸摸點 ...
  • 前言 給大家推薦一個專為新零售快消行業打造了一套高效的進銷存管理系統。 系統不僅具備強大的庫存管理功能,還集成了高性能的輕量級 POS 解決方案,確保頁面載入速度極快,提供良好的用戶體驗。 項目介紹 Dorisoy.POS 是一款基於 .NET 7 和 Angular 4 開發的新零售快消進銷存管理 ...
  • ABP CLI常用的代碼分享 一、確保環境配置正確 安裝.NET CLI: ABP CLI是基於.NET Core或.NET 5/6/7等更高版本構建的,因此首先需要在你的開發環境中安裝.NET CLI。這可以通過訪問Microsoft官網下載並安裝相應版本的.NET SDK來實現。 安裝ABP ...
  • 問題 問題是這樣的:第三方的webapi,需要先調用登陸介面獲取Cookie,訪問其它介面時攜帶Cookie信息。 但使用HttpClient類調用登陸介面,返回的Headers中沒有找到Cookie信息。 分析 首先,使用Postman測試該登陸介面,正常返回Cookie信息,說明是HttpCli ...
  • 國內文章 關於.NET在中國為什麼工資低的分析 https://www.cnblogs.com/thinkingmore/p/18406244 .NET在中國開發者的薪資偏低,主要因市場需求、技術棧選擇和企業文化等因素所致。歷史上,.NET曾因微軟的閉源策略發展受限,儘管後來推出了跨平臺的.NET ...
  • 在WPF開發應用中,動畫不僅可以引起用戶的註意與興趣,而且還使軟體更加便於使用。前面幾篇文章講解了畫筆(Brush),形狀(Shape),幾何圖形(Geometry),變換(Transform)等相關內容,今天繼續講解動畫相關內容和知識點,僅供學習分享使用,如有不足之處,還請指正。 ...
  • 什麼是委托? 委托可以說是把一個方法代入另一個方法執行,相當於指向函數的指針;事件就相當於保存委托的數組; 1.實例化委托的方式: 方式1:通過new創建實例: public delegate void ShowDelegate(); 或者 public delegate string ShowDe ...