2010-08-04 21 views
2

這是我的問題。更新後的DLL導致JNI拋出「Exception c0000005」

我有第三部分DLL(我沒有源代碼),我必須使用JNI來交談。提供此DLL的人不是Java-house。我在他們的DLL中發現了一個錯誤,所以編寫了一些C++,它們運行了它們的DLL,暴露了這個錯誤並將它發送給他們以進行修復。我終於從他們那裏得到了一個更新的DLL,運行了我的C++代碼(它工作正常),並發現bug確實已經修復。然而,現在當我在我的JNI代碼中使用這個新的DLL時,我得到了下面的異常:

Exception c0000005, at 1EEE3416 
Access violation: attempting to read memory at address 00000004 
Native function stack data: 0,3f49c0,20201,801c6,65637845,6f697470,3063206e,30303030 
com.jniwrapper.FunctionExecutionException: c0000005 
at com.jniwrapper.Function.invokeCFunc(Native Method) 
at com.jniwrapper.FunctionCall.a(SourceFile:127) 
at com.jniwrapper.FunctionCall.call(SourceFile:35) 
at com.jniwrapper.Function.invoke(SourceFile:188) 
at com.tme.techdoc3.diagnostic.api.denso.DensoApiInvoker.invoke(DensoApiInvoker.java:78) 
at com.tme.techdoc3.diagnostic.api.denso.NewDensoApi.invoke(NewDensoApi.java:106) 
at com.tme.techdoc3.diagnostic.api.denso.NewDensoApi.connect(NewDensoApi.java:46) 
at ConsoleApiRunner.main(ConsoleApiRunner.java:59) 

我實際使用JNIWrapper提供本人JNI代碼等來了統治他們的產品爲引起我寫我自己的JNI代碼,而不是一個問題;但我仍然得到這個相同的錯誤。這使我確信問題出在第三方DLL中。

我從我調用DLL的第一個函數(順便說一句,這個函數沒有它的bug ...)得到這個異常。

我們得到DLL的地方明確表示,他們不會支持它在JNI環境中的使用,即使他們不會向我發送任何類型的發行說明或固定和非固定鏈接之間的更改列表,固定的DLL。

在政治上,我無能爲力。實際上,我僅限於該供應商的DLL。

任何人都可以想到任何理由爲什麼這個DLL從C++調用時會起作用,但不是在JNI中調用時?我一直在玩JNI堆棧大小(-Xss)和其他一些JVM參數,但是我沒有選擇正確的設置,或者我看錯了。

任何想法,不勝感激。

非常感謝。

編輯:添加我自己的JNI代碼,看看是否有人可以發現一個錯誤。

編輯2:更正後的代碼複製粘貼錯誤。

當我使用我自己的JNI代碼時,下面是我正在使用的.cpp文件的實現;你可以看到,這很簡單,當我把指針等混在一起時,我看不到任何地方。 (免責聲明:這幾乎是我C++技能的總和!)

回答

0

c0000005指示「訪問違規」,這通常意味着已經使用了一個指針來保存無效的內存地址。這可能只是一個不好的指針值,例如未初始化或可能表明該對象已被銷燬。

我想看看兩件事情:

  1. 你逝去特別是任何類型的出來的參數。我沒有直接使用JNI,但是我想如果一個變量是隻讀的,而不是可以寫入的話,那麼一個變量可以橋接到C++。如果DLL API期望它們已被分配,請確保分配的任何緩衝區都已分配。

  2. 您調用方法或作爲參數傳遞的對象的生命週期。確保您正在使用的Java對象在調用C++期間未被收集。

+0

是的,糟糕的指針是我一直在網上閱讀的東西。麻煩的是,我無法將這一事實融入我所看到的代碼中。就像我說的那樣,直接從C++調用這個DLL工作正常,所以這意味着DLL本身沒問題,不是嗎? 所以你是對的,問題必須在JNI代碼中。但是,使用這個JNIWrapper產品並將老版本的DLL交換回來工作正常,但只要我交換到新版本,就會出現此錯誤 - 這意味着問題出在DLL中? – Tom 2010-08-04 15:04:44

+0

新的DLL可能正常工作,但性能或內存配置文件略有不同。這可能足以暴露先前隱藏的java/jni代碼中的錯誤。你可以試着挑起C++中的失敗,讓你知道在哪裏尋找。 – morechilli 2010-08-04 15:14:05

+0

是的你是對的。可悲的是,這是一個複製粘貼錯誤,而不是其他任何東西。 我已經有很多C++代碼在沒有任何問題的情況下運行第三方DLL,我可能會嘗試再次嘗試並嘗試使其失敗。 – Tom 2010-08-05 07:36:45

0

我的建議是基於這個假設 - 如果你能用C++工作,那麼你應該能夠在JNI中工作。

自從我使用JNI已經很長時間了,但這樣的問題通常是由最簡單的事情引起的。

我將非常徹底地檢查的是,您正在使用新DLL隨附的所有更新的.h頭文件/ .lib等文件。在檢查你指向所有新文件,正確的路徑(包括你當前的JRE)之後,重新生成你的JNI定義對象。搜索你的整個文件系統並刪除以前版本的舊DLL,它的依賴關係/ headers/libs/.obj等。一個陳舊的文件可能導致問題。

我曾經在一個問題上浪費了三天,因爲有些應用程序在其自己的程序目錄中放置了一個核心windows DLL的副本(然後添加到PATH中),這導致在嘗試加載正確程序時造成混亂。

順便說一下:該DLL有任何奇怪的身份驗證/許可行爲?還是需要加載它無法解決的其他依賴關係?

+0

只是挖出我的最後jni對象。它有: 的#ifdef __cplusplus 的extern 「C」{ #ENDIF ....所有的功能defns 的#ifdef __cplusplus } #ENDIF 我依稀記得有書面C++ VS C的DLL時出現問題生成的代碼可能會追溯到Java 1.4 如果您真的絕望編寫自己的調用他們的DLL的DLL,然後將您的Java代碼連接到您的DLL。然後通過拋出所有函數的參數進行調試 – james 2010-08-17 02:20:29

0

好的,這已解決(而不是解決)。

最近我意識到我一直在介紹一條紅鯡魚。當我編寫自己的JNI代碼(排除導致問題的JNIWrapper產品)並宣佈異常仍然被拋出時,我一定被困在DLL Hell的一個圈子裏。當我第一次引入自己的JNI代碼時,引發了異常,但在隨後的日子裏,重新運行我自己的JNI代碼並沒有拋出異常。所以我認爲我必須有一箇舊的DLL放在某處導致一些錯誤的結果。

So new information:與JNIWrapper一起使用時會拋出異常,但不會與本地JNI代碼一起使用。

所以現在我在JNIWrapper中深入挖掘。在他們的支持論壇帖子之一中,它表示JNI包裝器不是爲C++ DLL設計的,即它只支持C++語言功能的子集。虛擬方法是一個特殊的缺點。由於我的第三方DLL是C++版本,因此我認爲在以前的版本中他們使用的是不使用JNIWrapper的不支持的語言功能,但現在它們是。對我而言,這意味着我不能再使用JNIWrapper工具。

相反,我使用Swig來生成我需要的所有JNI代碼。無論如何,Swig看起來像是一個更好的選擇,因爲生成的Java代碼更清晰。

感謝大家給出的建議。我認爲每個答案的至少一個方面是正確和有幫助的。

相關問題