快速摘要:拋出:IllegalArgumentException在IKVM編譯DLL
我IKVM編譯JAR到DLL庫與在.NET項目的一些方法和類的工作,但一個特定拋出一個異常,似乎以表明我的IKVM.Runtime.JNI正在嘗試將一個64位地址存儲到一個32位變量,當我想要整個系統是32位。這會導致拋出IllegalArgumentException。
的問題
我有一個需要被集成到一個.NET項目的多個JAR文件的形式的Java API。 JAR文件根據CLASSPATH中的目錄搜索API的許可證和配置文件。 JAR文件也使用JNI調用來包含java.library.path中包含的DLL。
.NET項目有一個x86目標。 JNI包含的DLL有win64和win32版本,所以我使用win32目錄中的DLL。
這一切發生在VS2010,使用.NET Framework 4的操作系統是64位Windows 7
好了計劃,所以這一計劃是使用IKVM編譯器來編譯JAR文件到DLL。然後,將這些DLL與IKVM庫一起包含在.NET項目中,並且能夠以這種方式與JAVA API進行交互。
編譯
首先,我編譯log4j的罐子:
~>ikvmc -target:library log4j-1.2.14.jar
IKVM.NET Compiler version 7.3.4830.0
Copyright (C) 2002-2013 Jeroen Frijters
http://www.ikvm.net/
note IKVMC0002: Output file is "log4j-1.2.14.dll"
warning IKVMC0100: Class "javax.jms.MessageListener" not found
...
有大約20個左右的警告處理的javax.jms *和* javax.mail居多,但它。似乎編譯好。
然後,我把其餘的。
~>ikvmc -platform:x86 -target:library -classloader:ikvm.runtime.ClassPathAssemblyClassLoader -r:log4j-1.2.14 { commons-io-1.4.jar } { commons-lang3-3.1.jar } { EngineAPI_PC-1.0.13.jar } { EngineAPI_PC-api-1.0.13.jar } { guice_no_aop-3.0.jar } { guice-assistedinject-3.0.jar } { inject-330.jar } { IVectorsMultiSpeaker4GResources-1.0.1.jar } { IVectorsResources-1.0.6.jar } { slf4j-api-1.7.2.jar } { slf4j-log4j12-1.7.2.jar }
IKVM.NET Compiler version 7.3.4830.0
Copyright (C) 2002-2013 Jeroen Frijters
http://www.ikvm.net/
warning IKVMC0126: Found assembly "log4j-1.2.14" using legacy search rule, pleas
e append '.dll' to the reference
note IKVMC0002: Output file is "commons-io-1.4.dll"
note IKVMC0002: Output file is "commons-lang3-3.1.dll"
note IKVMC0002: Output file is "EngineAPI_PC-1.0.13.dll"
note IKVMC0002: Output file is "EngineAPI_PC-api-1.0.13.dll"
note IKVMC0002: Output file is "guice_no_aop-3.0.dll"
note IKVMC0002: Output file is "guice-assistedinject-3.0.dll"
note IKVMC0002: Output file is "inject-330.dll"
note IKVMC0002: Output file is "IVectorsMultiSpeaker4GResources-1.0.1.dll"
note IKVMC0002: Output file is "IVectorsResources-1.0.6.dll"
note IKVMC0002: Output file is "slf4j-api-1.7.2.dll"
note IKVMC0002: Output file is "slf4j-log4j12-1.7.2.dll"
warning IKVMC0112: Emitted java.lang.IllegalAccessError in "es.agnitio.core3.Voi
ceSampleImpl.getIdentifiableData()Ljava.util.List;"
("Try to access class es.agnitio.core3.a from class es.agnitio.core3.VoiceSa
mpleImpl")
(in EngineAPI_PC-1.0.13.dll)
warning IKVMC0112: Emitted java.lang.IllegalAccessError in "es.agnitio.core3.Voi
ceSampleImpl.getIdentifiableData()Ljava.util.List;"
("Try to access method es.agnitio.core3.a.<init>(Les.agnitio.core3.VoiceSamp
leImpl;Les.agnitio.core3.IdentifiableData;)V from class es.agnitio.core3.VoiceSa
mpleImpl")
(in EngineAPI_PC-1.0.13.dll)
如您所見,我看到-platform:x86以確保32位DLL。使用-classloader:...必須能夠稍後編輯CLASSPATH,包括帶有配置文件和許可證文件的目錄。我引用了log4j DLL並列出了其餘的JAR。在此之後,我爲每個文件都有DLL。
設置項目
在.NET項目中,我引用:
- 所有的DLL在IKVM/bin目錄中,除了IKVM母語 - * DLL
- 的JVM。 .DLL in IKVM/bin-x86
- 上一步中編譯的DLL。
我將ikvm-native-win32-x86.dll添加到項目中作爲包含在項目構建中的鏈接。我不會將任何IKVM EXE添加到項目中。我還應該注意,儘管能夠進行JNI調用,但項目調試輸出從來沒有表明它使用JVM.DLL或ikvm-native-win32-x86.dll。
我的項目有一個app.config,其中IKVM:的java.library.path和iKVM:java.class.path設置:
<appSettings>
<add key="ikvm:java.library.path" value="C:\path\to\DLLs\for\JNI;" />
<add key="ikvm:java.class.path" value="C:\path\to\config;C:\path\to\license;" />
</appSettings>
在app.config也擁有了所有IKVM組件綁定庫。
編譯和運行項目
我包括java.io和es.agnitio。*命名空間。我能夠使用JAVA項目中的方法和類併成功編譯。該庫還成功找到配置文件,許可證和JNI DLL文件。
當我運行該應用程序時,第一次調用JAVA函數暫停了一段時間,而JAVA庫被加載。在這一點上,我得到這個輸出:
[17:42:38.76691 ] loadLibrary: C:\path\to\DLLs\for\JNI\predj.dll, class loader: [email protected]
[17:42:38.80491 ] Library loaded: C:\path\to\DLLs\for\JNI\predj.dll, handle = 0xF800000
爲所有的JNI庫,我看到本地方法成功鏈接。在此之後,幾個Agnitio JAVA API類和方法按預期工作,並且我能夠執行JAVA文件IO。然而,一個特定的方法給出了這樣的例外:
*** exception in native code ***
java.lang.IllegalArgumentException: Can not set long field es.agnitio.data.Nativ
eMemoryJNI.ptrAddress to es.agnitio.core.ArrayForNativeCode
System.Collections.ListDictionaryInternal
Can not set long field es.agnitio.data.NativeMemoryJNI.ptrAddress to es.agnitio.
core.ArrayForNativeCode
at __<Setter>(IReflectionException , Object , Int64 , Object)
at IKVM.NativeCode.sun.reflect.ReflectionFactory.FieldAccessorImplBase.FieldA
ccessor`1.lazySet(Object obj, T value)
at IKVM.NativeCode.sun.reflect.ReflectionFactory.FieldAccessorImplBase.FieldA
ccessor`1.lazySet(Object obj, T value, FieldAccessor`1 acc)
at IKVM.NativeCode.sun.reflect.ReflectionFactory.FieldAccessorImplBase.LongFi
eld.setLong(Object obj, Int64 value)
at IKVM.Runtime.JNIEnv.SetLongField(JNIEnv* pEnv, IntPtr obj, IntPtr fieldID,
Int64 val)
at es.agnitio.ivectors.IVectorsNative.updateStreaming4GSessionS(ArrayForNativ
eCode afnc1, ArrayForNativeCode afnc2, ArrayForNativeCode afnc3)
at es.agnitio.ivectors.h.b(FeaturesNoJNA fnjna)
at es.agnitio.core3.internal.d.a(FrontEndResult fer, Int32 i1, Int32 i2)
at es.agnitio.core3.internal.d.a(Int32 i1, Int32 i2, List l)
at es.agnitio.core3.internal.b.extractVoiceSamples(Int32 i, List l)
at es.agnitio.core3.internal.b.extractVoiceSamples(Int32 i)
at es.agnitio.core3.internal.b.extractVoiceSample(List l)
at es.agnitio.modeling.ModelFactoryAbstract.a(List , List , List)
at es.agnitio.modeling.ModelFactoryAbstract.trainModelFromAudio(AudioStandard
as, List l)
at es.agnitio.modeling.ModelFactoryAbstract.trainModelFromAudio(AudioStandard
as)
at BS3Test.Program.Main(String[] args) in C:\path\to\source\Program.cs:line 38
我的思想
它看起來像Agnitio庫存儲在一個32位的變量某些對象的地址,但IKVM庫方法將其轉換爲64位地址,因此是IllegalArgumentException。網上有很多文檔說ikvm-native - *。dll決定JNI調用是以32位還是64位的方式進行的,但似乎並不像我的JVM.dll或ikvm-native-win32-x86.dll在這個過程中。關於如何解決這個問題的任何想法(或者更好的方式來整合這個JAVA庫)?
編輯:我最初的印象是不正確的。 ikvm-native-win32-x86.dll和JVM.dll已成功包含在32位版本的項目中。現在,我對於錯誤消息的含義有點不知所措。
你在es.agnitio.ivectors.IVectorsNative.updateStreaming4GSessionS方法中做了什麼? – Horcrux7