JNI Access Violation Excetpion

Hello all,

First of all, I am very new to JNI. I was putting together a little application to test JNI, but I keep getting an AccessViolationException when trying to access a jstring in my VC++ code.

// File: TestDll.dll

using namespace System;

using namespace System::Runtime::InteropServices;

[DllImport("user32")]

extern"C"long FindWindow( String^ windowClass, String^ windowName );

JNIEXPORT jlong JNICALL Java_Main_findWindow

(JNIEnv * env, jclass, jstring className, jstring windowName)

{

long handle = 0;

try{

constchar *nativeString;

nativeString = env->GetStringUTFChars( className,false );

handle = FindWindow(gcnew String(nativeString), nullptr);// for now use windowClass only

//DON'T FORGET THIS LINE!!!

env->ReleaseStringUTFChars( className, nativeString );

}

catch( System::AccessViolationException^ e )

{

Console::WriteLine(e->ToString());

}

return handle;

}

If i remove the lines about nativeString = env->GetStringUTFChars( windowClass,false);

handle = FindWindow(gcnew String(nativeString), nullptr);

and just call FindWindow("Notepad", nullptr)

from within the method, then I get no problems.

However, I want to pass the paramters from my Java code. I made sure I compiled the header file correctly, and the Java code is correct also I believe. The files are not long, so I will post them here.

//Main.java

publicclass Main

{

static

{

System.loadLibrary ("TestDll");

}

publicstaticvoid main (String ar[])

{

System.out.println ("Notepad has handle # " + findWindow ("Notepad",null));

}

publicstaticnativelong findWindow (String className, String windowName );

}

And heres he header file used by calling javah -jni Main

/* DO NOT EDIT THIS FILE - it is machine generated */

#include <jni.h>

/* Header for class Main */

#ifndef _Included_Main

#define _Included_Main

#ifdef __cplusplus

extern"C"{

#endif

/*

* Class:Main

* Method:findWindow

* Signature: (Ljava/lang/String;Ljava/lang/String;)J

*/

JNIEXPORT jlong JNICALL Java_Main_findWindow

(JNIEnv * env, jclass, jstring className, jstring windowName);

#ifdef __cplusplus

}

#endif

#endif

Again, I am not certain exactly what is causing the error, just that anytime I try and access one of the jstring

passed as a paramter, this exception is thrown. Here is the output from my application:

System.AccessViolationException: Attempted to read or writeprotected memory. This is often an indication that other memory is corrupt.

at JNIEnv_.GetStringUTFChars(JNIEnv_* , _jstring* str, Byte* isCopy)

at Java_Main_findWindow(JNIEnv_* env, _jclass* __unnamed001, _jstring* className, _jstring* windowName)

Notepad has handle # 0

Ugh! Just as I am writing this post, and had to run the my program one more time so that i could redirect the output to a text file for easy copy and past, IT WORKED. I dont know how or why. I changed nothing. However, I still wanna know why it was throwing the exception in the first place.

Thanks, Dale

[4792 byte] By [smithdale87a] at [2007-11-27 11:08:22]
# 1

I think Second parameter to env->GetStringUTFChars( className, false ); 'false' is creating problem. If you study about the "GetStringUTFChars" you will find that second paramter is address of variable.

SACHIN_SETH1203a at 2007-7-29 13:28:14 > top of Java-index,Java HotSpot Virtual Machine,Specifications...
# 2

thanks for your reply.

Most of the examples I have found on the net use a 3 parameter call to getStringUTFchars looking something similar to this:

const char *str = GetStringUTFChars( env, some_jstring, 0);

However when I try and add a third param in my dll file using VC++, i get a compile error saying:

error C2660: 'JNIEnv_::GetStringUTFChars' : function does not take 3 arguments

even though clearly in the stacktrace output I previously included, in one of the lines it says that JINEnv does take 3 params:

at JNIEnv_.GetStringUTFChars(JNIEnv_* , _jstring* str, Byte* isCopy)

I am not sure why but using 2 params is the only way i can get the dll to compile correctly.

That is why I used const char *cName;

const char *wName;

cName = env->GetStringUTFChars( className,false);

wName = env->GetStringUTFChars( windowName, false);

Also, as I said at the end of my first post, somehow the program worked a few times ( 3-4 ) without giving me the errors, and thus, gave me the intended output. However, I have not been able to get it to work since then, nor do I know what I did, or what happened so that it would work in the first place.

-Dale

Message was edited by:

smithdale87

smithdale87a at 2007-7-29 13:28:14 > top of Java-index,Java HotSpot Virtual Machine,Specifications...
# 3

<snip>

>

>

> Ugh! Just as I am writing this post, and had to run

> the my program one more time so that i could redirect

> the output to a text file for easy copy and past, IT

> WORKED. I dont know how or why. I changed nothing.

> However, I still wanna know why it was throwing the

> exception in the first place.

A rogue copy of the DLL file with bad code in it can cause such strange behavior.

Niceguy1a at 2007-7-29 13:28:14 > top of Java-index,Java HotSpot Virtual Machine,Specifications...
# 4

In your program use the ollowing statment

jbyte isCopy;

cName = env->GetStringUTFChars( className,&isCopy);

wName = env->GetStringUTFChars( windowName, &isCopy);

This will work.

You must have defined __cplusplus in your program. If you go through the jni.h you will understand why your program is expecting two arguments for GetStringUTFChars and most of the examples shows three arguments.

SACHIN_SETH1203a at 2007-7-29 13:28:14 > top of Java-index,Java HotSpot Virtual Machine,Specifications...