快速摘要:抛出: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