2012-03-09 76 views
1

我有一個內部使用java的C++程序(通過我的C++ dll包裝了內部使用jvm.dll的WebLogic jsmc.dll)。程序使用過時的(不是當前的)env變量值

當我在運行我的程序之前設置CLASSPATH時,找到所有JAR庫並且程序正常工作。 當我做不是設置CLASSPATH之前運行我的程序,JARs是而不是發現,這當然是預期的。

現在,當我設置運行我的程序前的CLASSPATH,但明確程序代碼這裏面CLASSPATH環境變量之前加載我的DLL使用Java,奇怪的事情發生了:所有的JAR仍然發現,程序就好像一切正​​常一樣。我通過幾種方式驗證了CLASSPATH實際上是從env變量中刪除的(例如通過使用ProcessExplorer或打印它的值)。

問題:

你能向我解釋這種行爲嗎?我是不是想知道爲什麼java忽略我設置的CLASSPATH,但是怎麼可能 java看到舊的CLASSPATH值,而不是當前的值?我強調,java不可能以某種方式存儲舊的CLASSPATH值,因爲在舊值可用時未加載java。

我該如何讓java尊重過程env變量中的更改?

詳情:

上述的問題只是我做了探索我真正的問題簡單化。我試圖從程序中設置CLASSPATH,並避免將它設置在外部。但是java使用了外部設置的CLASSPATH,而不是我在程序中設置的CLASSPATH。

我使用Windows API(GetEnvironmentVariableA,SetEnvironmentVariableA)讀取和設置env變量值。我已經驗證過,通過這種方式設置它們後,程序過程環境變量確實發生了變化我甚至在調用任何java方法之前,從使用java的dll打印CLASSPATH值。我使用ProcessMonitor檢查了jvm.dll真的被加載之後 CLASSPATH被刪除。我也試圖排除從父進程讀取CLASSPATH的可能性。現在我非常確定在加載jvm.dll時,CLASSPATH已經從進程環境中刪除。

我已經嘗試了Visual C++ 2010測試程序和HP LoadRunner C編譯器(mmdrv.exe)vuser腳本,結果相同。 LoadRunner是我需要解決這個問題的主要原因。

+0

您是否已經仔細檢查了所使用的CLASSPATH只能來自父進程(例如命令shell)而不是來自例如存儲在註冊表中的默認環境變量值? – 2012-03-10 05:06:47

+0

我設法讓代碼在Visual Studio中工作。將「jmsc.dll」標記爲延遲加載(屬性 - >鏈接器 - >輸入 - >延遲加載的Dll =「jmsc.dll」)就足夠了。 不幸的是,相同的代碼與LoadRunner的工作方式不一樣 - 即使dll是懶洋洋地加載的,加載的dll仍然使用原始的CLASSPATH,而不是修改過的。 : - (((可能在執行lr_load_dll()時出現一些怪癖) – xarx 2012-03-12 14:23:33

+0

一個可能的解釋是,jmsc.dll中包含或引用的C運行時可能在啓動時自己創建了環境變量副本。確定它們在jvm.dll中的結果如何:或許它使用相同的運行時,或者jmsc.dll明確地將CLASSPATH傳遞給jvm.dll出於某種原因,你需要用調試器來查看它以知道確定 – 2012-03-12 20:33:33

回答

1

問題是由該C-運行時莫名其妙緩存的環境變量引起的。當我嘗試使用系統函數SetEnvironmentVariableA()修改CLASSPATH時,jmsc.dll從C運行時緩存讀取CLASSPATH。 C運行時嘗試將其緩存與流程環境中的實際值進行同步,但顯然不是很成功。爲了更改CLASSPATH,我需要將來自C運行時的對_putenv()的調用替換爲SetEnvironmentVariableA()的系統調用。

但還有另一個問題。我的代碼使用了各種版本的C運行庫,每個版本都有自己的環境緩存。我的VC代碼與msvcr100.dll鏈接,而jmsc.dll(實例化Java VM)使用msvcrt.dll。解決方案是將我的代碼鏈接到msvcrt.dll,以便我的代碼使用來自jmsc.dll讀取的同一C運行時的_putenv()設置CLASSPATH。

由於哈利·約翰斯頓的重要提示,並彼得Cetinski有價值的信息。

0

從C++調用新的JVM進程時,不應該依賴CLASSPATH環境變量。 JNI接口提供了一種機制,用於在啓動時指定JVM的類路徑。

http://java.sun.com/docs/books/jni/html/invoke.html#28719

+0

好主意:)。但是,我沒有明確創建JVM,因此我無法設置JavaVMInitArgs的參數。我只使用jmsc.dll庫(用於JMS的Weblogic C-API)創建自己的JVM。如果我正確地取消了你的鏈接,如果我使用JNI_CreateJavaVM()創建了一個JVM,那將是一個新的JVM實例,與jmsc.dll創建的實例不同。 – xarx 2012-03-09 14:59:46

+0

你是對的,這將是一個不同的過程。我確信jmsc.dll只是調用JNI_CreateJavaVM。 – 2012-03-09 16:00:13

+0

那麼,我至少應該測試在創建新的JVM和在運行之前清除類路徑時會發生什麼。 – xarx 2012-03-09 16:07:02

相關問題