Using the Java Native Interface in C#
|
|
 |

|
Thanks for this Simon.
I added in code to call static methods, something you might consider in future.
I found some bugs:
1. when parsing a signature like (Ljava/lang/String;Ljava/lang/String;)V after the first part is extracted, the StartIndex should be incremented or the next signature selected is ';'
if (sig.Substring(startIndex, 1) == "L") {
paramSig = paramSig + sig.Substring(startIndex, sig.IndexOf(';', startIndex) - startIndex);
startIndex++; } else {
2. if a parameter is null then an exception is throw (seem my comment below)
if (param[i] is string) {
if (!paramSig.Equals("Ljava/lang/String")) {
....
} else if (param[i] == null) {
retval[i] = new JValue(); } else if (paramSig.StartsWith("[")) {
3. when handling arrays, the call to PackPrimitiveArray must specify the type (I also added the code to allow byte arrays)
} else if (paramSig.Equals("[C")) {
arrPointer = env.NewCharArray(((Array)param).Length, javaClass);
env.PackPrimitiveArray<char>((char[])param, arrPointer);
} else if (paramSig.Equals("[B")) {
arrPointer = env.NewByteArray(((Array)param).Length, javaClass);
env.PackPrimitiveArray<byte>((byte[])param, arrPointer);
} else if (paramSig.Equals("[S")) {
|
|
|
|

|
Hi Simon:
thanks for your work,but the application can not work on windows 8 ,x64-bit,jdk-x64.an error will occor when JNI_CreateJavaVM. so check the jdk dir,and can not find client\jvm.dll. after "google" some web page ,i install jdk-x86,the code works well.
|
|
|
|

|
Simon,
First, I want to thank you for making this library. There is no way I could have done it. I am currently on a project where I need to send in and receive objects, however this does not seem to work properly. I noticed JavaNativeInterface.CallMethod<T> does not check for a typeof(object). I am trying to get this to work this week for a proof of concept. I have begun to add to your library to do this, but I don't know what to do with the return object from IntPtr obj = env.CallObjectMethod(...) Can you lend a hand? I see what you did with strings and I wonder if I need something similar. I can send you any changes if you'd like. I have already added a lot of IntPtr cleanup per an earlier post.
|
|
|
|

|
Dear Simon,
First of all, thank you for your nice contribution and I would like to know more the ways you implemented in here.
Could it be possible to make further enhancement for the following examples of Data Types, Methods, Structures, Constructors and Classes shown in below.
////////////////////////////////////////////////////////////
// Code used in Java
public class TestServer
{
private string page;
public TestServer(String address, String port)
{
}
public byte[] send(SendClass txn, byte sendData[])
{
}
}
I am looking forward to heaign from you good news soon.
Thanks and best regards
PS : The actual implementation will be based on Java Sever Code(Web Service) with .NET
|
|
|
|

|
Hi
Thanks for letting me know about the issue you've found whilst using the components. I am very busy on another project at the moment but hope to have some time later on in the month to fix the issue.
Simon
|
|
|
|

|
You are not disposing a lot of your un-managed resources. Anytime you overwrite a IntPtr that does not equal zero or a local IntPtr goes out of scope you need to be calling env.DeleteLocalRef(ptrName);
Here are a few I found just doing some quick browsing (these are all in JavaNativeInterface.cs) There may be more in other classes.
public void InstantiateJavaObject(string ClassName)
{
javaClassName = ClassName;
IntPtr methodID = IntPtr.Zero;
try
{
if (javaClass != IntPtr.Zero) env.DeleteLocalRef(javaClass);
javaClass = env.FindClass(javaClassName);
methodID = env.GetMethodId(javaClass, "<init>", "()V");
if (javaObject != IntPtr.Zero) env.DeleteLocalRef(javaObject);
javaObject = env.NewObject(javaClass, methodID, new jValue() { });
}
catch
{
throw new Exception(env.CatchJavaException());
}
finally
{
if (methodID != IntPtr.Zero)
env.DeleteLocalRef(methodID); }
}
public void CallVoidMethod(string methodName, string sig, List<object> param)
{
IntPtr methodID = IntPtr.Zero;
try
{
methodID = env.GetMethodId(javaClass, methodName, sig);
env.CallVoidMethod(javaObject, methodID, ParseParameters(sig, param));
}
catch
{
throw new Exception(env.CatchJavaException());
}
finally
{
if (methodID != IntPtr.Zero)
env.DeleteLocalRef(methodID); }
}
private jValue[] ParseParameters(string sig, List<object> param)
{
}
public T CallMethod<T>(string methodName, string sig, List<object> param)
{
IntPtr methodID = IntPtr.Zero;
try
{
methodID = env.GetMethodId(javaClass, methodName, sig);
else if (typeof(T) == typeof(string))
{ IntPtr jstr = env.CallObjectMethod(javaObject, methodID, ParseParameters(sig, param));
string res = env.JStringToString(jstr);
env.DeleteLocalRef(jstr);
return (T)(object)res;
}
return default(T);
}
catch
{
throw new Exception(env.CatchJavaException());
}
finally
{
if (methodID != IntPtr.Zero)
env.DeleteLocalRef(methodID);
}
}
Also it would not hurt to make the class IDisposeable then dispose of javaClass, javaObject, and env and also tear down the jvm if this process started the jvm up instead of attaching to it.
|
|
|
|

|
Hi Simon,
Thanks for the article. It has been very useful. However I have a problem that you might be able to help me solve.
I am trying to get your library to work with java class files packaged in jar files. I modified the line setting the path to include the jar file but cannot access some files in the jar. Individual files packaged in the 'base directory' of the jar file are accessed with no problem. However I cannot seem to access any class files held in folders within the jar file. I have tried specifying the folder structure but to no avail.
Any idea what might be the problem. Am I doing something silly. It is a long time since I did much java development, so am not very familiar with the details now and I cannot find any reference to a similar problem. I thought the class loader would search the entire jar rather than me having to specify directory structure. I have to use JRE 1.4.2. Later versions don't work with the java package that I need to use.
Thanks for any help you might be able to give.
Cheers
Andrew
andreh123
metasens@iinet.net.au
|
|
|
|

|
Your code does not seem to handle array correctly. The array parameter starts with '[' rather than 'L'. The method ParseParameters does not check for '['.
thanks
Bill
|
|
|
|

|
Hi Simon,
I created jni4net library on top of very same idea few years ago. with jni4net you could also call back from Java to C#. Also it contains proxy generator, so you could use it in OOP way and user is abstracted from most of low level details. See http://jni4net.sourceforge.net/[^]
Drop me an email if you wish to join jni4net
Anyway, it's good that you wrote the article so everyone could understand the technical details.
Cheers
Pavel Savara
|
|
|
|
 |
|
|
Last Updated 22 Apr 2013 |
Advertise |
Privacy |
Terms of Use |
Copyright ©
CodeProject, 1999-2013