呼叫DLL路徑的迷思

因為修Bug,碰到和load dll路徑有關的議題。這個問題是: 在class path中加入Native的dll位置,但程式卻去找system32中的dll檔。在詢問我的好朋友谷哥後,找到這篇文章Windows 用來找出dll的搜尋路徑
經過多個試驗,發現將dll放在jre的bin與java執行檔同目錄,就可以比system32中的提早搜尋到。於是我想到: 即使dll沒放在java執行檔的路徑下,但我是有在工作目錄下放過dll,為何還是去讀取system32呢? (在這的java執行檔指的是jre/bin/java.exe)

我透過下面的實驗去確認找尋dll的順序。

Artifact

名稱關係用途
HelloWorld.exeLoad Dll1
HelloWorldDLL1.dllLoad Dll2輸出分別為DLL1-local、DLL1-work、DLL1-system
HelloWorldDLL2.dll 輸出分別為DLL2-local、DLL2-work、DLL2-system

其中工作目錄為C:,執行檔放置路徑為C:/Debug 。
輸出為DLL$-local的與執行檔放在一起;DLL$-work放置於工作目錄;DLL$-system放置於system32中。

測試案例

以下為我們測試的5種case:

案例動作結果
Case1於工作目錄執行Debug/HelloWorld.exeDLL1-local
DLL2-local
Case2刪除DLL2(local)DLL1-local
DLL2-system
Case3刪除DLL2(system)DLL1-local
DLL2-work
Case4還原所有DLL,刪除DLL1(local)DLL1-system
DLL2-local
Case5刪除DLL1(system)DLL1-work
DLL2-local

由以上五個case可以發現:dll的搜尋路徑是由執行檔路徑開始,接著是system32,最後是工作目錄。對Java而言,啟動jvm都是透過java指令,也就是java_home/bin/java.exe執行檔。因此放在java_home/bin中的dll,會比system32中的優先找到。後來我透過batch檔去執行Debug/HelloWorld.exe,結果發現搜尋的依據,是根據HelloWorld.exe而非batch檔。不管怎樣包裝,如果是A要去Load B,優先找尋的是A所在的目錄。