2013-09-27 88 views
2

我在Windows的C++應用程序中創建了一個JVM,我無法說服它加載多個JAR。在Windows上加載多個JAR-JNI JNI_CreateJavaVM

我的C++代碼:

MyClass::MyClass(std::string & classPath) { 
    classPath = "-cp "+classPath; // <-- Won't work with any path or single jar 
    //classPath = "-Djava.class.path="+classPath; <-- Only works with single jar 
    jvmOptions[0].optionString = (char *)classPath.c_str(); 
    jvmOptions[1].optionString = "-Xms8m"; 
    jvmOptions[2].optionString = "-Xmx24m"; 
    jvmArgs.version = JNI_VERSION_1_6; 
    jvmArgs.options = jvmOptions; 
    jvmArgs.nOptions = 3; 
    jvmArgs.ignoreUnrecognized = JNI_TRUE; 
    int jvmInitResult = CreateJavaVM(&jvm, (void**)&environment, &jvmArgs); 

    if(jvmInitResult >= 0) { 
     jclass loadedClass = environment->FindClass(MyClassName.c_str()); 
      ..... 

如果我傳遞給一個單獨的JAR通過我classPath可變的路徑,如"C:\path\myjar.jar",所述jclass變量位於細。但是,我的Java類需要額外的JAR才能運行,所以我需要將多個JAR傳遞給jvmOptions。當我試圖通過以下任何一種方式通過第二個或第三個JAR時,FindClass調用現在失敗。

C:\path\myjar.jar <--------- FindClass SUCCESS; can't use due to missing jars 
C:\path\myjar.jar;C:\path\secondjar.jar <-----FindClass FAIL 
C:\path\myjar.jar:C:\path\secondjar.jar <-----FindClass FAIL 
C:\path\* <-----FindClass FAIL 
C:\path\*.jar <-----FindClass FAIL 
"C:\path\myjar.jar;C:\path\secondjar.jar" <-----FindClass FAIL 
"C:\path\myjar.jar:C:\path\secondjar.jar" <-----FindClass FAIL 

我假設還有另一個選項,我沒有想到,但這使我瘋了。

+0

'jvmOptions [0] = .optionString(字符*)( 「 - Djava.class.path =」 +類路徑).c_str( );' - 首先,你不希望修改它,其次,指針在該語句之後搖擺不定。 – chris

+0

我同意,這一步是暫時的,但我需要一個快速動態的方式來改變這一點,而無需重新編譯,而我找到了正確的格式。該變量作爲命令行參數傳入。 – Samhain

+0

@chris評論過的行永遠不會工作,因爲''-Djava.class.path =「+ classPath'會創建一個臨時的'std :: string',在該語句結束時被銷燬。 'jvmOptions [0] .optionString'指向其上的無效內存。也許你想用'classPath.insert(...)'代替。 – Praetorian

回答

2

解決方案是在將參數傳遞給程序時不使用windows文件分隔符。 \結束了使用一個或多個\排序的轉義。將參數更改爲unix樣式文件分隔符會正確加載目錄中的所有jar。

例如:

MyApp "classpath" 
MyApp C:\pathtojars\ <-- fails 
MyApp C:/pathtojars/ <-- works 

固定碼:

MyClass::MyClass(std::string & classPath) 
{ 
    classPath = "-Djava.class.path="+classPath; 
    jvmOptions[0].optionString = (char *)classPath.c_str(); 
    jvmOptions[1].optionString = "-Xms8m"; 
    jvmOptions[2].optionString = "-Xmx24m"; 
    jvmArgs.version = JNI_VERSION_1_6; 
    jvmArgs.options = jvmOptions; 
    jvmArgs.nOptions = 3; 
    jvmArgs.ignoreUnrecognized = JNI_TRUE; 
    int jvmInitResult = CreateJavaVM(&jvm, (void**)&environment, &jvmArgs); 

    if(jvmInitResult >= 0) 
    { 
     jclass loadedClass = environment->FindClass(MyClassName.c_str()); 
     ..... 
+0

其實,我不認爲使用'/'真的是解決方案。我目前遇到包含通配符的類路徑問題,Google會將我帶到此網頁。我敢肯定的是,使用'-cp'不起作用,使用'*'(通配符來包含所有JAR)不起作用,'''''''''''\''視窗。我已經用Java 6,7和8測試過了。但是,如果直接在C/C++字符串中使用'「\」,不要忘記保護它:'「dir \\ file」'vs'「dir \ file」'。 至於'*',它似乎應該手動擴展,請參閱'java.c'中的'JLI_WildcardExpandClasspath()'。 – xav

+0

@xav我嘗試過和沒有逃脫測序;只有成功的選擇是使用unix風格的路徑分隔。其他選項是通過擴展類加載加載罐子:http://docs.oracle.com/javase/tutorial/ext/basics/load.html – Samhain

+0

奇怪......你正在使用哪種操作系統和JRE?對我來說,它是Win7-64位,Java 6/7/8,32/64位。我用Visual Studio 2010編譯我的EXE文件。 – xav

2

您應該使用-cp來設置類路徑。我懷疑-Djava.class.path=不會做你認爲應該的。

+0

將其切換到-cp,但仍然沒有。 'classPath =「-cp」+ classPath; jvmOptions [0] .optionString =(char *)classPath.c_str();' – Samhain

+0

@Samhain'-cp'和'-classpath'是兩個參數。 –

+0

修改爲傳遞4個jvmOptions,第一個是-cp,第二個是我的罐子的路徑,或者是jar的路徑。沒有成功。 'jvmOptions [0] .optionString =「-cp」; jvmOptions [1] .optionString =(char *)classPath.c_str(); jvmOptions [2] .optionString =「-Xms8m」; jvmOptions [3] .optionString =「-Xmx24m」;' – Samhain