use NativeLong or a Java primitive type of the appropriate size.
> I doubted it might be a calling convention issue. Here I posted what I found and appreciate any confirmations.
>
> Our java app calls a C_wrapper.dll which wraps a C++.dll. It's found that the C++ lib is StdCall calling convention while C_Wrapper.dll is a calling convention. So the java interface uses Library rather than StdCallLibrary. Will it be a problem?
>
Using different conventions at different interfaces shouldn't pose a problem.
> Using the Dependency Walker, here is the snap shot of the screen for C++.dll (it's said that if a function ends with @nnn, then it's a stdcall lib, right?)
@NN usually indicates stdcall; the patterns you see in the dependency walker for the C++ dll is due to C++ name mangling (encoding the method signature into the method name).
>
> <image.png>
> but the C_Wrapper.dll has functions like this,
>
> <image.png>
> On Wed, Feb 29, 2012 at 10:39 AM, Mike Jiang <mike...@gmail.com> wrote:
> Thanks, Tim.
> Current it didn't create any hs_err_id.log file, instead it popped up a jvm crash window like this,
>
> <image.png>
Is the native code compiled with gcc/mingw or MSVC? that will have an effect on whether setProtected() works or not (gcc/mingw doesn't use SEH normally, which is what JNA expects on windows in order for setProtected to work).
Try running with java.exe instead of javaw.exe, that may have an effect on whether the crash log gets created.
> Thanks.
> I also tried to use a non-zero value for the handle, the crash still occurred.
I would expect that the "open" call would provide you with a non-zero handle. If the handle is zero after the "open" call, then your library probably encountered an error and you shouldn't use the handle.
> the Wrapper native code was compiled with MS Visual Studio 2008. Should the native wrapper code be added some thing like try/catch for SEH? I am not familiar with SEH.
If the error is occurring during JVM shutdown, then proper setProtected operation is not the issue (although there may be additional spots in JNA native code which *should* be protected).
> I have identified which function calling caused the problem: sendCommand(handle, requestString). the calling to the function returns a success (=0), and it returns a correct response, but it might cause the problem. How did I prove it? I comment out the line to call the sendCommand(), then no jvm crash at all when the java app exits.
>
> So my problem is: everything is working as expected, until the java app exit-the jna tried to do dereferencing at the finalizer() and caused non-existing memory access violation. I have changed Memory.java by not freeing the memory. But it seemed not fixing the problem. I was a little bit confused.
Is it possible that the native code is freeing something passed to it by JNA? It's also possible that the native code has registered an atexit() handler that is failing (which might also explain the lack of a stack dump).
You might try null-ing all references and forcing a GC with System.gc() prior to exit, to see if you can trigger the error before the JVM starts to shut down.
> Thanks for the answer.
> Here is what I found,
>
> 1). after the openSession() function call, the handle has a nonzero value of long type. Then I used the value to call the next function, send Command(handle, requestString). No problem for it.
> 2). The SEH handling, should the native code is re-implemented to inculde the SEH handling? If that's the case, I might not do it since the original c++.dll is not ours. I can change the wrapper.dll. But I didn't know how to;
Not necessary. The violation is happening outside of normal code operation.
> 3). I have tested System.gc() prior to java app exits, still crashed;
> 4). here is the the c wrapper code, I didn't see native code is freeing something passed to it by JNA.
It wouldn't be in your code, it would be in the c++ dll you're using.
As a test, call "atexit" before calling anything from the C++ dll. You can put this in your wrapper code. call "atexit" again *after* calling the c++ dll, this time with a different handler.
This sets things up so that if the C++ dll *does* register an atexit handler, your handlers will be called on either side of it; if only one of your handlers is called before the crash, you know that the c++ dll is installing an atexit handler, and that handler is causing the error. At that point you need to refer to your DLL documentation. It's also possible that it's crashing while calling destructors for static C++ objects.
Aside from the crash on VM exit, do the other functions/methods seem to be behaving properly?
you should have Java pass in a byte[] or Memory (with its size) and have the C function fill in the buffer, rather than returning a pointer.
you could also return the address of a static or long-allocated buffer, but that's kind of clunky.
JNA will only free the memory that it allocates (and that is only ever done in the Memory object). It will never free something allocated by native code.
C++:
#define EXAMPLE_DLL extern "C" __declspec(dllexport)
EXAMPLE_DLL char* returnDLLVersion();
Java:
public interface ExampleDLL extends Library {
ExampleDLL INSTANCE = (ExampleDLL) Native.loadLibrary("example.dll", ExampleDLL.class);
String returnDLLVersion();
}
char* _result = NULL;
const char* myfunc() {
if (_result) free(_result);
_result = malloc(size_needed);
return _result;
> it is not single threaded. and no synchronization lock is used. what I can do is to move the global variable to a local variable.
>
> How about like this- don't create any any pointer,just return the c_str().
>
> CVCLIENT_DLL_C_WRAPPER_API const char* CVCWrapperSendCommand(CVCHANDLE CVCSessionHandle, int timeout, int tracing, const char* request)
> {
> CVCCommand g_cmd;
> g_cmd.nTimeout = timeout;
> g_cmd.ntracing = tracing;
> g_cmd.strXMLCommand = request;
>
> if(rc == CVCSUCCESS)
> {
> return g_cmd.strXMLResponse.c_str();
> }
> else {
> return "";
> }
> }
>
> No C++ compiler at hands. Don't know if it can be compiled. In this way, is there any new memory allocated?
>
>
A local variable is allocated on the stack. That variable goes out of scope when the function returns (as does the temporary buffer provided by the .c_str() call). In some cases, the compiler may avoid disposing of the std::string immediately, but I don't think there's any guarantee the above code would work.
If you absolutely *have* to return a block of memory, then allocate it with malloc, return it as a Pointer value, and free it with Native.free() in JNA.
JNA will automatically create and manage C strings when Java Strings are passed to the native app, but if you want to pass one from the native app back to JNA, you will need to use something equivalent to strdup (and later free the memory).
Note that if JNA automatically converts a "char*" to a String, you will not have a reference to the original pointer in order to be able to free the memory later. This is true whether the pointer is returned directly or as a field within a structure. In your case, you should probably make the field of type Pointer and extract the string manually. That way the pointer is available to be freed on the Java dide by calling Native.free().
String
is not appropriate since the java String is immutable... Instead it had better use byte[] or Memory, or NIO Buffer, etc. But you must know the length of the to-be-returned response string-which we don't know. > All my work is to return a string from the native code and java code just simply read the string. But according to the doc-it says A Java String is not appropriate since the java String is immutable... Instead it had better use byte[] or Memory, or NIO Buffer, etc.
The documentation refers to the case where your API requires that you pass in a buffer for the callee to fill.
In your case, you have control over the API, so you aren't locked into that particular method of "returning" a value.
However, if your function's return value is "char *", you must ensure that the memory is valid until JNA can create a Java String from it, and you need to provide for some method of freeing the memory (either doing so in your native code automatically or providing a "free" method for JNA to call).
> But you must know the length of the to-be-returned response string-which we don't know.
>
> So I still try to return the response as a java String. I am trying to wrap the response string(java String) in a Structure (CVCCommand) and then pass the CVCCommand by reference to the native function. It worked, But I don't know if there is any memory leak.
The most straightforward solution is to return the native-allocated memory, have JNA read it as a Pointer, extract the String via Pointer.getString(0), then call Native.free() (or something equivalent provided by your program) to free the memory.
You should *never* call Native.free() on any memory that JNA has allocated (that means Structure.getPointer()!)
>
> I used the Process Explorer to observe the memory usage. I can see the memory usage of the java process. But I am not sure if the usage also contains the memory used by the native code.
If Process explorer measures the memory usage of any given process, then the "java process" will include *all* memory, since it really has no notion of "Java" or "non-Java" memory.
Where's the stack/crash dump?
On Mar 22, 2012, at 9:03 AM, <mike...@gmail.com> <mike...@gmail.com> wrote:
> I will send the detail crashing info. Here I want to ask a quick question. Native.free(...) only takes a long, is there a way for using Pointer object rather than its native value when freeing memory? I did not find a method doing so.
>
>
>
>
>
> -- Sent from my HP TouchPad
> I used the jna3.4.0 and there is no Native.free(Pointer pointer) from the doc and from the class.
>
> I used a different way to do it since I can change the c_wrapper:
>
> 1). add a new function, freeIt(), to the .h and .cpp files:
>
> in .h file:
>
> extern "C" CVCLIENT_DLL_C_WRAPPER_API char* CVCWrapperSendCommand(CVCHANDLE CVCSessionHandle, int timeout, int tracing, const char* request);
> extern "C" CVCLIENT_DLL_C_WRAPPER_API void freeIt(char *s);
>
>
> 2). in java code, call to freeIt(Pointer p) to free the memory, and now it seemed no memory leak.
>
>
It would seem that your library and JNA are using different runtime libraries. Use a dependency tracking tool like "depends.exe" to see what your library is linked to versus what JNA is linked to (MSVCR*).
> You meant the C_wrapper.dll and JNA link to different versions of MSVCR*? Thanks for pointing that. I will check it after meeting.
> But one thing is still not clear: Is there a method: Native.free(Pointer p) I can call? I am using 3.4.0 version.
No, there is not; it should be added next release.
On Mar 22, 2012, at 5:12 PM, Mike Jiang wrote:
> Here is a screen snapshot of the dependency tool for C_Wrapper.dll. It is linked to use MSVCR90.dll and MSVCR90.dll.
>
> <image.png>
> Good point! You talked about the C_Wrapper.dll and the JNA use different MSVCR90.dll files? they use the same MSVCRT.dll.
> You mean I can still use Native.free(Pointer.nativeValue(pointer)) to deallocate the memory if the above issue is resolved?
I don't know which issue you're referring to.
If they use the same runtime, then Native.free() should be entirely equivalent to your native free() call.
const char* read(int start, int end)
This return type (const char*) is mapped to String in Java. But I need
char[] or byte[]. I tried java interface
public abstract byte[] read(int start, int end);
and
public abstract char[] read(int start, int end);
but both ends with java.lang.IllegalArgumentException: Unsupported
return type class [C in function read.
So is there any way how map C return array of char to java char[]? Or
byte* to byte[] (I could change return type in C function). I have
problem with encoding - I dont know it at application start and it could
be different for every JNA call, so I need array of primitive type.
System.setProperty("jna.encoding", X) isn't solution for me :(