重寫 hashcode真有那么簡單嘛?( 二 )

  • 簡單來說:我們在日常編程中看到native修飾的方法,只需要知道這個方法的作用是什么,至于別的就不用管了,操作系統會給我們實現 。
原來是這樣,要是我寫的代碼也能這樣就好了,我就寫個方法,用 native 修飾,然后操作系統就給我自動實現 。
想的美了,其實操作給我們實現,也是其他程序員寫好的代碼提前編譯好了,換句話來說就是:哪有歲月靜好 , 只是有猿替你負重前行罷了 。
  • 作為一個Java程序員 , 我們還是想了解一些底層JDK代碼的 。所以,必須把源碼扒出來,哪怕看不懂 。(這是openjdk中的源碼) 。
JDK目錄
  • 知識盲區,有一說一,能把 JDK 源碼讀懂的人,真大神也 。
openjdk├ corba:不流行的多語言、分布式通訊接口├ hotspot:Java 虛擬機├ jaxp:XML 處理├ jaxws:一組 XML web services 的 Java API├ jdk:java 開發工具包├ langtools:Java 語言工具└ nashorn:JVM 上的 JavaScript 運行時hotspot目錄
  • 什么叫源碼,什么叫底層,這就叫專業?。。?/li>
hotspot├─agentServiceability Agent的客戶端實現├─make用來build出HotSpot的各種配置文件├─srcHotSpot VM的源代碼│├─cpuCPU相關代碼(匯編器、模板解釋器、ad文件、部分runtime函數在這里實現)│├─os操作系相關代碼│├─os_cpu操作系統+CPU的組合相關的代碼│└─share平臺無關的共通代碼│├─tools工具││├─hsdis反匯編插件││├─IdealGraphVisualizer將server編譯器的中間代碼可視化的工具││├─launcher啟動程序“java”││├─LogCompilation將-XX:+LogCompilation輸出的日志(hotspot.log)整理成更容易閱讀的格式的工具││└─ProjectCreator生成Visual Studio的project文件的工具│└─vmHotSpot VM的核心代碼│├─adlc平臺描述文件(上面的cpu或os_cpu里的*.ad文件)的編譯器│├─asm匯編器接口│├─c1client編譯器(又稱“C1”)│├─ci動態編譯器的公共服務/從動態編譯器到VM的接口│├─classfile類文件的處理(包括類加載和系統符號表等)│├─code動態生成的代碼的管理│├─compiler從VM調用動態編譯器的接口│├─gc_implementationGC的實現││├─concurrentMarkSweepConcurrent Mark Sweep GC的實現││├─g1Garbage-First GC的實現(不使用老的分代式GC框架)││├─parallelScavengeParallelScavenge GC的實現(server VM默認,不使用老的分代式GC框架)││├─parNewParNew GC的實現││└─sharedGC的共通實現│├─gc_interfaceGC的接口│├─interpreter解釋器,包括“模板解釋器”(官方版在用)和“C++解釋器”(官方版不在用)│├─libadt一些抽象數據結構│├─memory內存管理相關(老的分代式GC框架也在這里)│├─oopsHotSpot VM的對象系統的實現│├─optoserver編譯器(又稱“C2”或“Opto”)│├─primsHotSpot VM的對外接口,包括部分標準庫的native部分和JVMTI實現│├─runtime運行時支持庫(包括線程管理、編譯器調度、鎖、反射等)│├─services主要是用來支持JMX之類的管理功能的接口│├─shark基于LLVM的JIT編譯器(官方版里沒有使用)│└─utilities一些基本的工具類└─test單元測試hashcode() 真源碼
  • 在openjdk8根路徑/hotspot/src/share/vm/runtime路徑下的synchronizer.cpp文件中,有生成哈希值的代碼:
static inline intptr_t get_next_hash(Thread * Self, oop obj) {intptr_t value = https://www.huyubaike.com/biancheng/0 ;if (hashCode == 0) {// 返回隨機數value = os::random() ;} elseif (hashCode == 1) {//用對象的內存地址根據某種算法進行計算intptr_t addrBits = cast_from_oop(obj) >> 3 ;value = addrBits ^ (addrBits >> 5) ^ GVars.stwRandom ;} elseif (hashCode == 2) {// 始終返回1,用于測試value = 1 ;} elseif (hashCode == 3) {//從0開始計算哈希值value = ++GVars.hcSequence ;} elseif (hashCode == 4) {//輸出對象的內存地址value = cast_from_oop(obj) ;} else {// 默認的hashCode生成算法,利用xor-shift算法產生偽隨機數unsigned t = Self->_hashStateX ;t ^= (t << 11) ;Self->_hashStateX = Self->_hashStateY ;Self->_hashStateY = Self->_hashStateZ ;Self->_hashStateZ = Self->_hashStateW ;unsigned v = Self->_hashStateW ;v = (v ^ (v >> 19)) ^ (t ^ (t >> 8)) ;Self->_hashStateW = v ;value = v ;}value &= markOopDesc::hash_mask;if (value == 0) value = 0xBAD ;assert (value != markOopDesc::no_hash,"invariant") ;TEVENT (hashCode: GENERATE) ;return value;}先上一首涼涼 。不是看不懂啊,畢竟大學學過C , 但是腦瓜子嗡嗡的,肯定不能專研這個了,先跳過 , 回到正題 。
為什么要重寫hashcode我們大概知道了,那如果我偏不重寫呢 , 先來個鐵頭娃demo看看效果 。

推薦閱讀