voiceinsight
2008-07-30 10:47:26 UTC
Hi,
First let me say that I find IKVM extremely useful. Also, I was extremely
impressed to see it run an application of mine (several jar's, loads native
DLLs through JNA) on the first try ! So: Jeroen, thanks a million!
Now to the issues: I am new to .NET, I know Java (not confident with class
loaders). I am unclear about IKVM's class loading mechanisms. I have read
(though perhaps not fully understood)
http://weblog.ikvm.net/PermaLink.aspx?guid=8a457a80-1e5f-4182-8f78-b2cd67845553
. I'd like to find a fix for the issues I'm encountering, described below.
I'm using the latest stable release 0.36.0.11
I use several methods to execute my application. To start with, I looked at
bin/starter.cs and took inspiration from it to run my application. In all
cases I ikvmc-compile everything, referencing some Dll's I need, and
specifying "-classloader:ikvm.runtime.ClassPathAssemblyClassLoader" (not
that I exactly know why I'm doing that...).
- method 1: (works fine up to a point, see below) set java classpath with
Startup.setProps(); use reflection methods to construct and manipulate Java
objects (to do this I use java.lang.Class.forName("com.mynamespace.MyClass",
true, ClassLoader.getSystemClassLoader() - which I got from starter.cs, I'm
not sure I'm using it correctly)
- method 2: set java classpath with Startup.setProps(); reference
ikvmc-generated Dlls in project, and directly use Java objects on .Net code
- method 3: set java classpath with java.lang.System.setProperty() from
within .Net; reference ikvmc-generated Dlls in project, and directly use
Java objects on .Net code
To work further with method 1, my issue is that I can't seem to cast an
object obtained through Constructor.newInstance() into its actual Java type.
If I try
----
object c = constructor.newInstance(null); // creates a MyClass instance
MyClass c2 = (MyClass) c;
----
.NET will complain on the second line with
----
System.InvalidCastException: Unable to cast object of type
'com.mynamespace.MyClass' to type 'com.mynamespace.MyClass'.
----
With method 2 and 3, my issue is the following. I use JNA (www.jna.org) to
access a native library in my Java project. The native library also performs
callbacks to my Java code. All of this works fine using method 1, provided I
reference ikvm-native.dll in my Visual Studio project. However, it won't
work any more if I do one of the following
- use method 1': set java classpath through java.lang.System.setProperty
from within .NET (instead of using Startup.setProps())
- use my methods 2 or 3: i.e. replace reflection by direct Java object
manipulation in .NET
In either case, it will fail on the first callback the native Dll performs,
with the following error message:
----
*** exception in native code ***
System.AccessViolationException: Attempted to read or write protected
memory. Th
is is often an indication that other memory is corrupt.
at com.sun.jna.Pointer._getInt(Int64 l)
java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Method.java:625)
at
com.sun.jna.CallbackReference$DefaultCallbackProxy.callback_inner(Cal
lbackReference.java:272)
at
com.sun.jna.CallbackReference$DefaultCallbackProxy.callback(CallbackR
eference.java:294)
at IKVM.Runtime.JNIEnv.InvokeHelper(Unknown Source)
at IKVM.Runtime.JNIEnv.CallObjectMethodA(Unknown Source)
Caused by: cli.System.AccessViolationException: Attempted to read or write
prote
cted memory. This is often an indication that other memory is corrupt.
at com.sun.jna.Pointer._getInt(Native Method)
at com.sun.jna.Pointer.getInt(Pointer.java:425)
at com.sun.jna.Structure.readField(Structure.java:382)
at com.sun.jna.Structure.read(Structure.java:278)
at com.sun.jna.Structure.readField(Structure.java:365)
at com.sun.jna.Structure.read(Structure.java:278)
at com.sun.jna.Structure.toArray(Structure.java:998)
at com.mynamespace.MyClass.extractArray(Dll.java:338)
----
The reason why I tried to replace Startup.setProps() by
java.lang.System.setProperty() for the java classpath is that it seemed to
solve an earlier issue I had, namely when using log4j, I would get
----
log4j:ERROR A "org.apache.log4j.ConsoleAppender" object is not assignable to
a "
org.apache.log4j.Appender" variable.
log4j:ERROR The class "org.apache.log4j.Appender" was loaded by
log4j:ERROR [log4j-1.2.14, Version=0.0.0.0, Culture=neutral,
PublicKeyToken=null
] whereas object of type
log4j:ERROR "org.apache.log4j.ConsoleAppender" was loaded by
[sun.misc.Launcher$
***@55c1be].
log4j:ERROR Could not instantiate appender named "A1".
----
My log4j.properties file is
----
# Set root logger appender to A1.
log4j.rootLogger=ALL, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
# Print the date in ISO 8601 format
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d %-5p %c.%M:%L - %m%n
----
Why are there several loaders for these classes ? I'm not sure I understand
the mechanisms...
What is the difference between setting the java classpath one way or the
other ?
What is the difference (in terms of classloaders etc perhaps) between
manipulating java objects using reflection or directly ? Why is there an
impact on JNI/JNA ?
Does it make a difference if I -reference:ikvm-native.dll when generating
the Dll using ikvmc ? I do it, but I'm not sure whether I should.
What is the effect of Startup.enterMainThread() ?
Please ask back for details or a worked-out test case if I'm unclear. I'll
need to work myself through this at any rate, and using IKVM seems the most
promising tool to use. Especially, seeing that it can actually run my app
(JNA/JNI code included) under some circumstances, I'm quite confident there
is a way to stabilize it when using another paradigm.
Thanks.
Sebastien
First let me say that I find IKVM extremely useful. Also, I was extremely
impressed to see it run an application of mine (several jar's, loads native
DLLs through JNA) on the first try ! So: Jeroen, thanks a million!
Now to the issues: I am new to .NET, I know Java (not confident with class
loaders). I am unclear about IKVM's class loading mechanisms. I have read
(though perhaps not fully understood)
http://weblog.ikvm.net/PermaLink.aspx?guid=8a457a80-1e5f-4182-8f78-b2cd67845553
. I'd like to find a fix for the issues I'm encountering, described below.
I'm using the latest stable release 0.36.0.11
I use several methods to execute my application. To start with, I looked at
bin/starter.cs and took inspiration from it to run my application. In all
cases I ikvmc-compile everything, referencing some Dll's I need, and
specifying "-classloader:ikvm.runtime.ClassPathAssemblyClassLoader" (not
that I exactly know why I'm doing that...).
- method 1: (works fine up to a point, see below) set java classpath with
Startup.setProps(); use reflection methods to construct and manipulate Java
objects (to do this I use java.lang.Class.forName("com.mynamespace.MyClass",
true, ClassLoader.getSystemClassLoader() - which I got from starter.cs, I'm
not sure I'm using it correctly)
- method 2: set java classpath with Startup.setProps(); reference
ikvmc-generated Dlls in project, and directly use Java objects on .Net code
- method 3: set java classpath with java.lang.System.setProperty() from
within .Net; reference ikvmc-generated Dlls in project, and directly use
Java objects on .Net code
To work further with method 1, my issue is that I can't seem to cast an
object obtained through Constructor.newInstance() into its actual Java type.
If I try
----
object c = constructor.newInstance(null); // creates a MyClass instance
MyClass c2 = (MyClass) c;
----
.NET will complain on the second line with
----
System.InvalidCastException: Unable to cast object of type
'com.mynamespace.MyClass' to type 'com.mynamespace.MyClass'.
----
With method 2 and 3, my issue is the following. I use JNA (www.jna.org) to
access a native library in my Java project. The native library also performs
callbacks to my Java code. All of this works fine using method 1, provided I
reference ikvm-native.dll in my Visual Studio project. However, it won't
work any more if I do one of the following
- use method 1': set java classpath through java.lang.System.setProperty
from within .NET (instead of using Startup.setProps())
- use my methods 2 or 3: i.e. replace reflection by direct Java object
manipulation in .NET
In either case, it will fail on the first callback the native Dll performs,
with the following error message:
----
*** exception in native code ***
System.AccessViolationException: Attempted to read or write protected
memory. Th
is is often an indication that other memory is corrupt.
at com.sun.jna.Pointer._getInt(Int64 l)
java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Method.java:625)
at
com.sun.jna.CallbackReference$DefaultCallbackProxy.callback_inner(Cal
lbackReference.java:272)
at
com.sun.jna.CallbackReference$DefaultCallbackProxy.callback(CallbackR
eference.java:294)
at IKVM.Runtime.JNIEnv.InvokeHelper(Unknown Source)
at IKVM.Runtime.JNIEnv.CallObjectMethodA(Unknown Source)
Caused by: cli.System.AccessViolationException: Attempted to read or write
prote
cted memory. This is often an indication that other memory is corrupt.
at com.sun.jna.Pointer._getInt(Native Method)
at com.sun.jna.Pointer.getInt(Pointer.java:425)
at com.sun.jna.Structure.readField(Structure.java:382)
at com.sun.jna.Structure.read(Structure.java:278)
at com.sun.jna.Structure.readField(Structure.java:365)
at com.sun.jna.Structure.read(Structure.java:278)
at com.sun.jna.Structure.toArray(Structure.java:998)
at com.mynamespace.MyClass.extractArray(Dll.java:338)
----
The reason why I tried to replace Startup.setProps() by
java.lang.System.setProperty() for the java classpath is that it seemed to
solve an earlier issue I had, namely when using log4j, I would get
----
log4j:ERROR A "org.apache.log4j.ConsoleAppender" object is not assignable to
a "
org.apache.log4j.Appender" variable.
log4j:ERROR The class "org.apache.log4j.Appender" was loaded by
log4j:ERROR [log4j-1.2.14, Version=0.0.0.0, Culture=neutral,
PublicKeyToken=null
] whereas object of type
log4j:ERROR "org.apache.log4j.ConsoleAppender" was loaded by
[sun.misc.Launcher$
***@55c1be].
log4j:ERROR Could not instantiate appender named "A1".
----
My log4j.properties file is
----
# Set root logger appender to A1.
log4j.rootLogger=ALL, A1
log4j.appender.A1=org.apache.log4j.ConsoleAppender
# Print the date in ISO 8601 format
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%d %-5p %c.%M:%L - %m%n
----
Why are there several loaders for these classes ? I'm not sure I understand
the mechanisms...
What is the difference between setting the java classpath one way or the
other ?
What is the difference (in terms of classloaders etc perhaps) between
manipulating java objects using reflection or directly ? Why is there an
impact on JNI/JNA ?
Does it make a difference if I -reference:ikvm-native.dll when generating
the Dll using ikvmc ? I do it, but I'm not sure whether I should.
What is the effect of Startup.enterMainThread() ?
Please ask back for details or a worked-out test case if I'm unclear. I'll
need to work myself through this at any rate, and using IKVM seems the most
promising tool to use. Especially, seeing that it can actually run my app
(JNA/JNI code included) under some circumstances, I'm quite confident there
is a way to stabilize it when using another paradigm.
Thanks.
Sebastien
--
View this message in context: http://www.nabble.com/IKVM-classloader-mechanism-%2B-loading-native-DLLs-with-JNA-tp18730665p18730665.html
Sent from the IKVM .NET - Dev mailing list archive at Nabble.com.
View this message in context: http://www.nabble.com/IKVM-classloader-mechanism-%2B-loading-native-DLLs-with-JNA-tp18730665p18730665.html
Sent from the IKVM .NET - Dev mailing list archive at Nabble.com.