EXCEPTION_ACCESS_VIOLATION when exiting from the java app

1,415 views
Skip to first unread message

Mike J

unread,
Feb 28, 2012, 10:47:06 AM2/28/12
to Java Native Access
Hi,
I have a java app to call a native C wrapper lib of a C++ dll lib
through JNA. JNA provides a very simple way to access the existing
third party lib.

The C++ lib has 4 functions for us to call:

openSession(String hostname, int port, String user, String pass,
LongByReference sessionHandle),
sendCommand(long handle, int timeout, int tracing, String
request),
getResponse(long handle, byte[] buff, IntByReference len);
closeSession(long handle),

The symptom is: invocation of the above four operations from the
java app have no problem. Everything worked perfect, thanks for the
well done JNA access to the native lib. However, the crashing occurred
when the java app exit with the error:
-----------------------------------------------------
# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x76e573dd, pid=5952,
tid=9360
#
# JRE version: 6.0_24-b07
# Java VM: Java HotSpot(TM) Client VM (19.1-b02 mixed mode windows-
x86 )
# Problematic frame:
# C [ntdll.dll+0x673dd]
----------------------------------------------------
I read the posts regarding to the issue online. For our case,
It's found that when closing the session, the native C++ lib freed the
memory internally. When the java code exits, the finalize process
tried second time to free the no-long existing memory, which caused
the problem.

My problem is: how can I avoid it? We don't have a control over
the native C++ lib-simply use the dll as it is. And the java app will
do the GA collection, also out of our control.

Appreciate any helps


Timothy Wall

unread,
Feb 28, 2012, 12:08:35 PM2/28/12
to jna-...@googlegroups.com
Java long (64 bits) != C long (32 or 64 bits, depending on platform)

use NativeLong or a Java primitive type of the appropriate size.

Mike Jiang

unread,
Feb 28, 2012, 1:28:02 PM2/28/12
to jna-...@googlegroups.com
Thanks, Tim.

Here the c type is long long. I followed the JNA guide to do the mappings. Looked like calling the sendCommand() always got the crashing.

Here are the c wrapper header definitions,

#ifdef CVCLIENT_DLL_C_WRAPPER_EXPORTS
#define CVCLIENT_DLL_C_WRAPPER_API __declspec(dllexport)
#else
#define CVCLIENT_DLL_C_WRAPPER_API __declspec(dllimport)
#endif

#define CVCWRAPPER_ERR_NORESPONSE MAKE_ERR_RETCODE(FACILITY_BORG, 0x10001)
#define CVCHANDLE unsigned long long

typedef struct
{
  char*    strIPAddress;
  char*    strHostname;
  int       nPort;
} CVCTargetSystemC;

typedef struct
{
  char*  strUsername;
  char*  strPassword;
  char*  strGroup;
  char*  strRole;
} CVCUserIdentificationC;

extern "C" CVCLIENT_DLL_C_WRAPPER_API CVCRC CVCWrapperOpenSession(CVCTargetSystemC & TargetSystem, CVCUserIdentificationC & UserInfo, CVCHANDLE & CVCSessionHandle);
extern "C" CVCLIENT_DLL_C_WRAPPER_API CVCRC CVCWrapperCloseSession(CVCHANDLE CVCSessionHandle);
extern "C" CVCLIENT_DLL_C_WRAPPER_API CVCRC CVCWrapperSendCommand(CVCHANDLE CVCSessionHandle, int timeout, int tracing, const char* request);
extern "C" CVCLIENT_DLL_C_WRAPPER_API CVCRC CVCWrapperGetResponse(CVCHANDLE CVCSessionHandle, char* response, int& len);

and actual java mappings are,

public interface CVLib extends Library {
CVLib INSTANCE = (CVLib) Native.loadLibrary("CVClient_DLL_C_Wrapper",
CVLib.class);

class CVCTargetSystem extends Structure {
public String strIPAddress;
public String strHostname;
public int nPort;

}
class CVCUserIdentification extends Structure {
public String strUsername;
public String strPassword;
public String strGroup;
public String strRole;
}

int CVCWrapperOpenSession(CVCTargetSystem targetSystem,
CVCUserIdentification userInfo, LongByReference sessionHandle);

int CVCWrapperCloseSession(long sessionHandle);

int CVCWrapperSendCommand(long sessionHandle, int timeout, int tracing,
String request);

int CVCWrapperGetResponse(long sessionHandle, byte[] response,
IntByReference len);

Mike Jiang

unread,
Feb 28, 2012, 4:02:27 PM2/28/12
to jna-...@googlegroups.com
I also used Native.setProtected(true) and tried to avoid invalid Access and throw java exception of it. It seemed not working either. the platform is Windows Vista and Native.isProtected() returns true.

Timothy Wall

unread,
Feb 29, 2012, 9:19:44 AM2/29/12
to jna-...@googlegroups.com
* you might want to verify with some standard system mappings to ensure your platform is working properly. ordinarily I wouldn't expect that to be an issue, but setProtected should normally catch null pointer dereferences like your error shows (please post the crash log dump), unless the error is happening outside of JNA's protection scope.
* normally, a null pointer dereference points to invalid data/parameters passed to the native function; can you provide the code that's invoking your mapped interfaces?
* I'm not entirely certain that the C++ expression "<type>&" unambiguously maps to "<type>*" with respect to the shared library interface. Since you're writing the wrapper, you might consider tweaking the exported API definition to use <type>* instead of <type>&.
* check that your java struct sizes match your native struct sizes; if your native code does some uncommon packing/alignment, the sizes may not agree.

Mike Jiang

unread,
Feb 29, 2012, 10:39:37 AM2/29/12
to jna-...@googlegroups.com
Thanks, Tim.
Current it didn't create any hs_err_id.log file, instead it popped up a jvm crash window like this,

Inline image 1

Here is the java test code,

import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.NativeLibrary;
import com.sun.jna.Pointer;
import com.sun.jna.PointerType;
import com.sun.jna.Structure;
import com.sun.jna.ptr.IntByReference;
import com.sun.jna.ptr.LongByReference;

public class CVClientTester {

CVLib.CVCTargetSystem target = new CVLib.CVCTargetSystem();
CVLib.CVCUserIdentification user = new CVLib.CVCUserIdentification();
Long clientHandle = null;
static final String requestString = "<Envelope xmlns='abc'>...</Envelope>";
static LongByReference handle = null;

public interface CVLib extends Library {
CVLib INSTANCE = (CVLib) Native.loadLibrary("CVClient_DLL_C_Wrapper",
CVLib.class);

class CVCTargetSystem extends Structure {
public String strIPAddress;
public String strHostname;
public int nPort;

}

class CVCUserIdentification extends Structure {
public String strUsername;
public String strPassword;
public String strGroup;
public String strRole;
}

class CVCCommand extends Structure {
public int timeout;
public int tracing;
public String command;
public String response;
}

int CVCWrapperOpenSession(CVCTargetSystem targetSystem,
CVCUserIdentification userInfo, LongByReference sessionHandle);

int CVCWrapperCloseSession(Long sessionHandle);

int CVCWrapperSendCommand(Long sessionHandle, int timeout, int tracing,
String request);

int CVCWrapperGetResponse(Long sessionHandle, byte[] response,
IntByReference len);
}

public static void main(String[] args) {
Native.setProtected(true);
System.out.println("is memory access protected? "
+ Native.isProtected());
CVLib.CVCCommand cvcCommand = new CVLib.CVCCommand();
CVClientTester tester = new CVClientTester();
tester.openSession("hostname", "hostIP", port,
"userId", "password");
cvcCommand.timeout = 0;
cvcCommand.tracing = 0;
cvcCommand.command = requestString;
tester.sendRequest(cvcCommand);
String s = tester.getResponse();
tester.closeSession();
}

public int openSession(String hostname, String ip, int port,
String username, String password) {
target.strHostname = hostname;
target.strIPAddress = ip;
target.nPort = port;

user.strUsername = username;
user.strPassword = password;

System.out.println("openSession: Connecting via CV Client to EVA at "
+ target.strIPAddress);

handle = new LongByReference();
int returnCode = CVLib.INSTANCE.CVCWrapperOpenSession(target, user,
handle);
clientHandle = new Long(handle.getValue());

System.out.println("openSession: clientHandle returned is "
+ clientHandle);
System.out
.println("openSession: Successfully Connected via CV Client to EVA at "
+ target.strIPAddress + " Return code = " + returnCode);
return returnCode;
}

int returnCode;

public int sendRequest(final CVLib.CVCCommand command) {
System.out
.println("sendRequest: Sending request via CV Client to EVA at "
+ target.strIPAddress);
returnCode = CVLib.INSTANCE.CVCWrapperSendCommand(clientHandle,
command.timeout, command.tracing, command.command);

System.out
.println("sendRequest: CV Client returned code " + returnCode);

return returnCode;
}

public String getResponse() {
String rval = null;
IntByReference len = new IntByReference(0);
int ok = -9999;
try {

ok = CVLib.INSTANCE.CVCWrapperGetResponse(clientHandle, null, len);
System.out.println("getResponse: len is " + len.getValue());
} catch (Throwable t) {
System.out.println("getResponse: sssss = " + t.getMessage());
}
if (ok == 0 && len.getValue() > 0) {
byte[] buffer = new byte[len.getValue()];
System.out
.println("getResponse:Get response for last CVClient request");
ok = CVLib.INSTANCE
.CVCWrapperGetResponse(clientHandle, buffer, len);
if (ok == 0) {
rval = Native.toString(buffer);
System.out.println("getResponse: rval is " + rval);
} else {
System.out.println("getResponse:Failed to get respons: "
+ Integer.toHexString(ok));
}
} else {
System.out.println("getResponse: Failed to get response length: "
+ Integer.toHexString(ok));
}
return rval;
}

public int closeSession() {
int returnCode = CVLib.INSTANCE.CVCWrapperCloseSession(clientHandle);
System.out.println("closeSession: Successfully close the Session: "
+ returnCode);
return returnCode;
}

}

the printout indeed shown the memory access is protected:

is memory access protected? true

Maybe the location of the setprotected() is not right? 

Thanks.
image.png

Mike Jiang

unread,
Feb 29, 2012, 6:21:27 PM2/29/12
to jna-...@googlegroups.com
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 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?)

Inline image 1 
but the C_Wrapper.dll has functions like this,

Inline image 2
image.png
image.png
image.png

Timothy Wall

unread,
Feb 29, 2012, 7:39:10 PM2/29/12
to jna-...@googlegroups.com

On Feb 29, 2012, at 6:21 PM, Mike Jiang wrote:

> 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>

Mike Jiang

unread,
Feb 29, 2012, 8:52:25 PM2/29/12
to jna-...@googlegroups.com
Yea, you are right.Thanks.
Do you have a chance to look at the code I posted here? I saw the error from the popped up window is C0000005. it's an exception_access_violation, right? But the crash no longer created hs_err_id.log. I cannot know what was causing the problem.

Even if the issue remains, if the crash error can be caught as a null exception by setting Native.setProtected(true), that will be good also. Unfortunately, it was still not there.

My dev box is a windows vista  enterprise s2 (32 bit os).

Timothy Wall

unread,
Mar 1, 2012, 7:03:17 AM3/1/12
to jna-...@googlegroups.com
I don't see anything obviously wrong with the code. You should check all your values before any crashing call to ensure they're in the range you expect (i.e. a handle value of zero going into a call will almost certainly result in the c0000005 error (which is a null-pointer dereference/exception_access_violation).

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.

Mike Jiang

unread,
Mar 1, 2012, 2:48:50 PM3/1/12
to jna-...@googlegroups.com
Thanks.
   I also tried to use a non-zero value for the handle, the crash still occurred.
   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.
   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.

Timothy Wall

unread,
Mar 1, 2012, 3:28:16 PM3/1/12
to jna-...@googlegroups.com

On Mar 1, 2012, at 2:48 PM, Mike Jiang wrote:

> 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.

Mike Jiang

unread,
Mar 1, 2012, 3:51:15 PM3/1/12
to jna-...@googlegroups.com
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;
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. 

#include<Windows.h>

#include <map>

#include "cvclientdefdll.h"
#include "CVClient_DLL_C_Wrapper.h"
#include "ComCriticalSectionSingleLock.h"


// Work around heap corruption caused by CVClientSendCommand() requires CVCCommand structure
// be globally defined. We therefore need to serialize calls to CVClientSendCommand() using 
// a global critical section...
CComAutoCriticalSection g_lock;
CVCCommand              g_cmd;


// The last response for each CVClient session
map<CVCHANDLE, string>  g_responses;


CVCTargetSystem TargetSystemC2Cpp(CVCTargetSystemC & TargetSystemC)
{
    CVCTargetSystem TargetSystemCpp;

if (TargetSystemC.strIPAddress != 0)
{
 TargetSystemCpp.strIPAddress = TargetSystemC.strIPAddress;
}

if (TargetSystemC.strHostname != 0)
{
 TargetSystemCpp.strHostname = TargetSystemC.strHostname;
}

TargetSystemCpp.nPort = TargetSystemC.nPort;

return TargetSystemCpp;
}

CVCUserIdentification UserIdentificationC2Cpp(CVCUserIdentificationC & UserIdentificationC)
{
CVCUserIdentification UserIdentificationCpp;

if (UserIdentificationC.strUsername != 0)
{
 UserIdentificationCpp.strUsername = UserIdentificationC.strUsername;
}

if (UserIdentificationC.strPassword != 0)
{
UserIdentificationCpp.strPassword = UserIdentificationC.strPassword;
}

if (UserIdentificationC.strGroup != 0)
{
 UserIdentificationCpp.strGroup    = UserIdentificationC.strGroup;
}

if (UserIdentificationC.strRole != 0)
{
 UserIdentificationCpp.strRole     = UserIdentificationC.strRole;
}

return UserIdentificationCpp;
}

CVCLIENT_DLL_C_WRAPPER_API CVCRC CVCWrapperOpenSession(CVCTargetSystemC & TargetSystemC, CVCUserIdentificationC & UserInfoC, CVCHANDLE & CVCSessionHandle)
{
    CVCTargetSystem TargetSystemCpp = TargetSystemC2Cpp(TargetSystemC);
CVCUserIdentification UserIdentificationCpp = UserIdentificationC2Cpp(UserInfoC);

CVCRC cvcrc = CVClientOpenSession(TargetSystemCpp, UserIdentificationCpp, CVCSessionHandle);

return cvcrc;
}

CVCLIENT_DLL_C_WRAPPER_API CVCRC CVCWrapperCloseSession(CVCHANDLE CVCSessionHandle)
{
CVCRC cvcrc = CVClientCloseSession(CVCSessionHandle);
return cvcrc;
}

CVCLIENT_DLL_C_WRAPPER_API CVCRC CVCWrapperSendCommand(CVCHANDLE CVCSessionHandle, int timeout, int tracing, const char* request)
{
CComCriticalSectionSingleLock lock(g_lock);

g_cmd.nTimeout = timeout;
g_cmd.ntracing = tracing;
g_cmd.strXMLCommand = request;
g_cmd.strXMLResponse.clear();

CVCRC rc = CVClientSendCommand(CVCSessionHandle, g_cmd);
if(rc == CVCSUCCESS)
{
g_responses[CVCSessionHandle] = g_cmd.strXMLResponse;
}

return rc;
}

CVCLIENT_DLL_C_WRAPPER_API CVCRC CVCWrapperGetResponse(CVCHANDLE CVCSessionHandle, char* response, int& len)
{
CComCriticalSectionSingleLock lock(g_lock);

CVCRC rc = CVCSUCCESS;

map<CVCHANDLE, string>::iterator lastResponse = g_responses.find(CVCSessionHandle);
if(lastResponse != g_responses.end())
{
if(len > 0)
{
if(response != NULL)
{
strncpy_s(response, len, lastResponse->second.c_str(), lastResponse->second.length());
g_responses.erase(lastResponse);
}
else
{
rc = CVCLIENT_ERR_ALLOCATION;
}
}
else
{
// return required buffer size
len = lastResponse->second.length() + 1;
}
}
else
{
// no last response
rc = CVCWRAPPER_ERR_NORESPONSE;
}

return rc;
}

Timothy Wall

unread,
Mar 1, 2012, 5:00:54 PM3/1/12
to jna-...@googlegroups.com

On Mar 1, 2012, at 3:51 PM, Mike Jiang wrote:

> 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?

Timothy Wall

unread,
Mar 5, 2012, 1:12:15 PM3/5/12
to Java Native Access


On Mar 1, 2:48 pm, Mike Jiang <mikej1...@gmail.com> wrote:
> Thanks.
>    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.
>

Perhaps the native library is attempting to free some piece of data
passed to it by "sendCommand"?
What makes you think that JNA is running a finalizer on exit, or that
the java app is the one triggering the exception? If the error were
happening from within the VM, you would get a VM stack dump. However,
if the exception happens within a native thread unknown to the VM,
you'll get no stack dump.

Mike Jiang

unread,
Mar 5, 2012, 3:11:35 PM3/5/12
to jna-...@googlegroups.com
Hi Tim,
     After checking the code carefully, it's found that the cause was from the native code lib, rather than the JNA. In a sense, the JNA has nothing to do with the JVM crashing. I really enjoy using the JNA there.
  

     The problem was rooted in the original C++ lib, CVClient.dll. There seemed to be a memory corruption for the CVCommand (a structure).cvCommandResponse because deleting it would cause an invalid memory access error if declaiming the CVCommand as a local variable.

     But if moving the CVComand back to a global variable, and indirectly assign the passed in request string to the CVCommand.CVCommandRequest, then the problem is fixed. No thing needs to be changed in JNA/java side.

     Thanks a lot for your help.

Mike Jiang

unread,
Mar 7, 2012, 7:19:50 PM3/7/12
to jna-...@googlegroups.com
I tried to optimize the function, sendCommand(...) and have it return the response(a string) instead an int. Here are the three parts.

1). the signature change in the .h file,

extern "C" CVCLIENT_DLL_C_WRAPPER_API const char* CVCWrapperSendCommand(CVCHANDLE CVCSessionHandle, int timeout, int tracing, const char* request);

2). the implementation in the .cpp wrapper,

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;

CVCRC rc = CVClientSendCommand(CVCSessionHandle, g_cmd);
        const char* response = "failed";
if(rc == CVCSUCCESS)
{
response = g_cmd.strXMLResponse.c_str();
}

return &response[0];      
}

here the pointer to the String is returned, so I can not call the delete[] to release the memory allocated for the pointer here. I remembered the jna is going to the memory releasing when the java app exits, right. That is, the Memory.disclose() calls Native.free() to release any memory held by the returned pointer. Is this the correct implementation?

3). the java interface to the function,

String CVCWrapperSendCommand(long sessionHandle, int timeout, int tracing,String request);


Please let me know if there is any problem.

Thanks for the help.

Timothy Wall

unread,
Mar 7, 2012, 10:10:00 PM3/7/12
to jna-...@googlegroups.com
g_cmd is allocated on the stack; the C string representation isn't guaranteed to be valid after function return. You wouldn't want to call delete[] on that memory anyway, since it's managed by the std::string object.

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.

Mike Jiang

unread,
Mar 7, 2012, 11:03:01 PM3/7/12
to jna-...@googlegroups.com
Thanks the answer, Tim.
I can pass in a byte[] or Memory, but I don't know the size since the size of the response gotten in the c++ code is not a fixed one.

I saw an example from the link: http://www.viaboxxsystems.de/java-interoperation-with-a-native-dll-using-jna

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();
}

Timothy Wall

unread,
Mar 8, 2012, 7:13:41 AM3/8/12
to jna-...@googlegroups.com
if your call is only ever called from a single thread, you can just allocate the space as needed:

char* _result = NULL;

const char* myfunc() {
if (_result) free(_result);
_result = malloc(size_needed);
return _result;

Mike Jiang

unread,
Mar 8, 2012, 7:50:08 AM3/8/12
to jna-...@googlegroups.com
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?

Timothy Wall

unread,
Mar 8, 2012, 10:32:00 AM3/8/12
to jna-...@googlegroups.com

On Mar 8, 2012, at 7:50 AM, Mike Jiang wrote:

> 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.

Mike Jiang

unread,
Mar 13, 2012, 9:31:02 PM3/13/12
to jna-...@googlegroups.com
What I am trying to do now is to pass a structure object to the native wrapper code like

in .h file,
#define CVCLIENT_DLL_C_WRAPPER_API __declspec(dllexport)
extern "C" CVCLIENT_DLL_C_WRAPPER_API const char* CVCWrapperSendCommand(CVCHANDLE CVCSessionHandle, CVCCommand & cmd);   //cmd is passed by reference here.

typedef struct
{
  string    strRequest;                                   // here java calling class passes the strRequest to the native wrapper function CVCWrapperSendCommand(...) and inserts the response string  
  int        timeout;                                        // to strResponse and java code reads the strResponse from the Structure object
  int        tracing;
  string    strResponse;
} CVCCommand;


in CVClient_DLL_C_Wrapper.cpp file

CVCLIENT_DLL_C_WRAPPER_API CVCRC CVCWrapperSendCommand(CVCHANDLE CVCSessionHandle, CVCCommand & cmd)
 {
          CVCRC rc = CVClientSendCommand(CVCSessionHandle, cmd);  //CVCRC is an insigned int
          return rc;
 }

in java class,

public interface CVLib extends Library {
CVLib INSTANCE = (CVLib) Native.loadLibrary("CVClient_DLL_C_Wrapper",
CVLib.class);

class CVCCommand extends Structure {
public String strRequest;
 public int timeout;
public int tracing;
                   public String strResponse;

}

  int CVCWrapperSendCommand(long sessionHandle, CVCCommand command);      
}

by calling the CVCWrapperSendCommand(..., CVCCommand command) in java code, I expect to get the responseString from the CVCCommand.strResponse.
But when I ran it, immediately an invalid memory exception was thrown, due to a bad match between java's strRequest (a java String type) in CVCCommand(a java Structure object) and a c++ 's strRequest (a c++ string) in CVCCommand (a c++ struct).

How a c++ std::string map to a java's corresponding type?

Timothy Wall

unread,
Mar 14, 2012, 4:15:32 PM3/14/12
to jna-...@googlegroups.com
There is no automatic translation between std::string and a Java String. You need to allocate and deallocate C strings yourself.

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().

Mike Jiang

unread,
Mar 20, 2012, 6:16:59 PM3/20/12
to jna-...@googlegroups.com
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. 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.

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.
And I saw there are two columns for memory usage, "private bytes" and "working set". It said that if the private bytes increases, then there is a memory leak.  Is it true?

Here are the code snippets:

1). in the wrapper.h file:
typedef struct
{
  char*  strRequest;
  int    nTimeout;
  int    ntracing;
  const char*  strResponse;
} CVCCommandC;

extern "C" CVCLIENT_DLL_C_WRAPPER_API CVCRC CVCWrapperSendCommand(CVCHANDLE CVCSessionHandle, CVCCommandC & cvcCommand);

2). in the wrapper.cpp file:

CVCCommand TargetCommandC2Cpp(CVCCommandC & TargetCommandC)
{
    CVCCommand TargetCommandCpp;

if (TargetCommandC.strRequest != 0)
{
TargetCommandCpp.strXMLCommand = TargetCommandC.strRequest;
}

TargetCommandCpp.nTimeout = TargetCommandC.nTimeout;

TargetCommandCpp.ntracing = TargetCommandC.ntracing;
TargetCommandCpp.strXMLResponse.clear();

return TargetCommandCpp;
}

CVCLIENT_DLL_C_WRAPPER_API CVCRC CVCWrapperSendCommand(CVCHANDLE CVCSessionHandle, CVCCommandC & cvcCommandC)
{
    CVCCommand cvcCommandCpp = TargetCommandC2Cpp(cvcCommandC);

    CVCRC rc = CVClientSendCommand(CVCSessionHandle, cvcCommandCpp);
    cvcCommandC.strResponse = strdup1(cvcCommandCpp.strXMLResponse.c_str()); 
    return rc; 
}

CVCLIENT_DLL_C_WRAPPER_API char *strdup1(const char *s) {
    char *d = (char*)malloc (strlen (s) + 1);   // Space for length plus nul        Does it every time allocate some memory from the heap? who is going to free it? the JNA code?
    if (d == NULL) return NULL;          // No memory
    strcpy (d,s);                        // Copy the characters
    return d;                            // Return the new string
}

3). in the java code:

public static class CVCCommand extends Structure
{
public String request;
public int timeout;
public int tracing;
public String response;
}

and the calling code is like,

  public class CVClienttester  {

CVLib.CVCCommand command = new CVLib.CVCCommand();
        String requestString = "...";
             ...
public static void main(String[] args)
{
CVClientTester tester = new CVClientTester();
for (int i = 0; i < 10000; i++)                                    //loop over 10000 times to see if there is any memory leak
{
System.out.println("the ith = " + i);

tester.openSession("asasasasasas.net", "1.1.1.1", 6666, "aaa", "aaaa");
try
{
String resp = tester.sendRequest(requestString, 0, 2);
}
catch (Throwable t)
{
System.out.println("the error msg is " + t.getMessage());
System.exit(0);
}
tester.closeSession();
}
}


public String sendRequest(String requestString, int timeout, int tracing) throws Throwable
{

command.timeout = timeout;
command.tracing = tracing;
command.request = requestString;
command.response = null;

int result = CVLib.INSTANCE.CVCWrapperSendCommand(clientHandle, command);
final String response = new String(command.response);
System.out.println("the response in structure is " + response);
EMClient.buildElementFromString(response);
// Native.free(Pointer.nativeValue(command.getPointer()));        //if I free the memory allocated by the structure like this, an EXCEPTION_ACCESS_VIOLATION (0xc0000005) will //              happen.  So I use Structure's clear() method for it. Does it cause the memory leak?
command.clear();
return response;
}
}

Timothy Wall

unread,
Mar 21, 2012, 7:04:00 AM3/21/12
to jna-...@googlegroups.com

On Mar 20, 2012, at 6:16 PM, Mike Jiang wrote:

> 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.

Mike Jiang

unread,
Mar 21, 2012, 12:06:17 PM3/21/12
to jna-...@googlegroups.com
Thanks for the reply.
Here I changed the code to have the native wrapper return the memory and have the java side receive it as a pointer. It worked and the response string was indeed obtained on the java side. But when I tried to free the memory related to the Pointer on the java side, it causes the EXCEPTION_ACCESS_VIOLATION (0xc0000005).


Here are the codes:

1). in .h file,

extern "C" CVCLIENT_DLL_C_WRAPPER_API char* CVCWrapperSendCommand(CVCHANDLE CVCSessionHandle, int timeout, int tracing, const char* request);

2). in .cpp file,

CVCLIENT_DLL_C_WRAPPER_API char* CVCWrapperSendCommand(CVCHANDLE CVCSessionHandle, int timeout, int tracing, const char* request)
{
CVCCommand commandCpp;
commandCpp.nTimeout = timeout;
commandCpp.ntracing = tracing;
commandCpp.strXMLCommand = request;
CVCRC rc = CVClientSendCommand(CVCSessionHandle, commandCpp);
return strdup1(commandCpp.strXMLResponse.c_str()); 
}

CVCLIENT_DLL_C_WRAPPER_API char *strdup1(const char *s) {
    char *d = (char*)malloc (strlen (s) + 1);   // Space for length plus nul
    if (d == NULL) return NULL;          // No memory
    strcpy (d,s);                        // Copy the characters
    return d;                            // Return the new string
}

3). in .java file,

Pointer CVCWrapperSendCommand(long sessionHandle, int timeout, int tracing, String request);

public String sendRequest(String requestString, int timeout, int tracing) throws Throwable
{

Pointer responsePointer = CVLib.INSTANCE.CVCWrapperSendCommand(clientHandle, command.timeout, command.tracing,
command.request);
final String response = responsePointer.getString(0);      //indeed got the response string with no problem
System.out.println("the response in structure is " + response);
Native.free(Pointer.nativeValue(responsePointer));        // this line caused EXCEPTION_ACCESS_VIOLATION (0xc0000005)
return response;
}

Is the method to free the memory pointed by the Pointer called right?

Timothy Wall

unread,
Mar 22, 2012, 7:01:16 AM3/22/12
to jna-...@googlegroups.com
You should be using the Pointer object, not Pointer.nativeValue, but that's not the cause of the problem.

Where's the stack/crash dump?

mike...@gmail.com

unread,
Mar 22, 2012, 9:03:06 AM3/22/12
to jna-...@googlegroups.com
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

Mike Jiang

unread,
Mar 22, 2012, 9:55:35 AM3/22/12
to jna-...@googlegroups.com
Here is the dump info:

#
# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x773f7d5a, pid=8972, tid=9092
#
# JRE version: 6.0_24-b07
# Java VM: Java HotSpot(TM) Client VM (19.1-b02 mixed mode windows-x86 )
# Problematic frame:
# C  [ntdll.dll+0x67d5a]
#
# If you would like to submit a bug report, please visit:
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#

---------------  T H R E A D  ---------------

Current thread (0x015abc00):  JavaThread "main" [_thread_in_native, id=9092, stack(0x00380000,0x003d0000)]

siginfo: ExceptionCode=0xc0000005, reading address 0x00000004

Registers:
EAX=0x1894a420, EBX=0x008f0000, ECX=0x00000000, EDX=0x00000000
ESP=0x003cfa9c, EBP=0x003cfac4, ESI=0x1894a418, EDI=0x18956718
EIP=0x773f7d5a, EFLAGS=0x00210246

Register to memory mapping:

EAX=0x1894a420
0x1894a420 is pointing to unknown location

EBX=0x008f0000
0x008f0000 is pointing to unknown location

ECX=0x00000000
0x00000000 is pointing to unknown location

EDX=0x00000000
0x00000000 is pointing to unknown location

ESP=0x003cfa9c
0x003cfa9c is pointing into the stack for thread: 0x015abc00
"main" prio=6 tid=0x015abc00 nid=0x2384 runnable [0x003cf000]
   java.lang.Thread.State: RUNNABLE

EBP=0x003cfac4
0x003cfac4 is pointing into the stack for thread: 0x015abc00
"main" prio=6 tid=0x015abc00 nid=0x2384 runnable [0x003cf000]
   java.lang.Thread.State: RUNNABLE

ESI=0x1894a418
0x1894a418 is pointing to unknown location

EDI=0x18956718
0x18956718 is pointing to unknown location


Top of Stack: (sp=0x003cfa9c)
0x003cfa9c:   00000000 18956718 008f0000 fffffffe
0x003cfaac:   0000000a 003cfa90 00000000 003cfbac
0x003cfabc:   77399ac2 01f3b2f9 003cfbbc 773f714a
0x003cfacc:   008f0000 18956718 003cfb6c 00000000
0x003cfadc:   76f11aed 00000000 008f0000 18956720
0x003cfaec:   000014dd 0000002b 015a9880 6d89d109
0x003cfafc:   000014dd 015ac290 003cfc20 6d9620f4
0x003cfb0c:   00000000 008f0000 008f3bb0 01b9b526 

Instructions: (pc=0x773f7d5a)
0x773f7d4a:   85 c9 32 01 00 8b 56 0c 8d 46 08 8b 08 89 4d f0
0x773f7d5a:   8b 49 04 89 55 f4 8b 12 3b d1 0f 85 c8 34 01 00 


Stack: [0x00380000,0x003d0000],  sp=0x003cfa9c,  free space=318k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
C  [ntdll.dll+0x67d5a]
C  [ntdll.dll+0x6714a]
C  [ntdll.dll+0x67385]
C  [kernel32.dll+0x49a26]
C  [msvcrt.dll+0x9c03]
C  [jna1195621861765249770.dll+0x6d51]
j  com.sun.jna.Native.free(J)V+0
j  CVClientTester.sendRequest(Ljava/lang/String;II)Ljava/lang/String;+94
j  CVClientTester.main([Ljava/lang/String;)V+56
v  ~StubRoutines::call_stub
V  [jvm.dll+0xf0ab9]
V  [jvm.dll+0x1837d1]
V  [jvm.dll+0xf0b3d]
V  [jvm.dll+0xfa0d6]
V  [jvm.dll+0x101cde]
C  [javaw.exe+0x2155]
C  [javaw.exe+0x8614]
C  [kernel32.dll+0x4d0e9]
C  [ntdll.dll+0x416c3]
C  [ntdll.dll+0x41696]

Java frames: (J=compiled Java code, j=interpreted, Vv=VM code)
j  com.sun.jna.Native.free(J)V+0
j  CVClientTester.sendRequest(Ljava/lang/String;II)Ljava/lang/String;+94
j  CVClientTester.main([Ljava/lang/String;)V+56
v  ~StubRoutines::call_stub

---------------  P R O C E S S  ---------------

Java Threads: ( => current thread )
  0x01b5c800 JavaThread "Low Memory Detector" daemon [_thread_blocked, id=8204, stack(0x18190000,0x181e0000)]
  0x01b57000 JavaThread "CompilerThread0" daemon [_thread_blocked, id=6832, stack(0x18140000,0x18190000)]
  0x01b40000 JavaThread "JDWP Command Reader" daemon [_thread_in_native, id=9404, stack(0x180f0000,0x18140000)]
  0x01b3e400 JavaThread "JDWP Event Helper Thread" daemon [_thread_blocked, id=9748, stack(0x180a0000,0x180f0000)]
  0x01b3bc00 JavaThread "JDWP Transport Listener: dt_socket" daemon [_thread_blocked, id=9800, stack(0x17ea0000,0x17ef0000)]
  0x01b0c000 JavaThread "Attach Listener" daemon [_thread_blocked, id=7732, stack(0x17db0000,0x17e00000)]
  0x01b09000 JavaThread "Signal Dispatcher" daemon [_thread_blocked, id=7744, stack(0x17d60000,0x17db0000)]
  0x01b00000 JavaThread "Finalizer" daemon [_thread_blocked, id=7724, stack(0x17d10000,0x17d60000)]
  0x01afb400 JavaThread "Reference Handler" daemon [_thread_blocked, id=9144, stack(0x17cc0000,0x17d10000)]
=>0x015abc00 JavaThread "main" [_thread_in_native, id=9092, stack(0x00380000,0x003d0000)]

Other Threads:
  0x01af7c00 VMThread [stack: 0x17c70000,0x17cc0000] [id=1580]
  0x181f0800 WatcherThread [stack: 0x183e0000,0x18430000] [id=9072]

VM state:not at safepoint (normal execution)

VM Mutex/Monitor currently owned by a thread: None

Heap
 def new generation   total 4928K, used 2006K [0x03b60000, 0x040b0000, 0x090b0000)
  eden space 4416K,  45% used [0x03b60000, 0x03d55b80, 0x03fb0000)
  from space 512K,   0% used [0x03fb0000, 0x03fb0000, 0x04030000)
  to   space 512K,   0% used [0x04030000, 0x04030000, 0x040b0000)
 tenured generation   total 10944K, used 0K [0x090b0000, 0x09b60000, 0x13b60000)
   the space 10944K,   0% used [0x090b0000, 0x090b0000, 0x090b0200, 0x09b60000)
 compacting perm gen  total 12288K, used 3684K [0x13b60000, 0x14760000, 0x17b60000)
   the space 12288K,  29% used [0x13b60000, 0x13ef9320, 0x13ef9400, 0x14760000)
No shared spaces configured.

Dynamic libraries:
0x00400000 - 0x00424000 C:\Program Files\Java\jre6\bin\javaw.exe
0x77390000 - 0x774b8000 C:\Windows\system32\ntdll.dll
0x76b50000 - 0x76c2c000 C:\Windows\system32\kernel32.dll
0x769d0000 - 0x76a96000 C:\Windows\system32\ADVAPI32.dll
0x76c80000 - 0x76d43000 C:\Windows\system32\RPCRT4.dll
0x75d80000 - 0x75e1d000 C:\Windows\system32\USER32.dll
0x76c30000 - 0x76c7b000 C:\Windows\system32\GDI32.dll
0x76b30000 - 0x76b4e000 C:\Windows\system32\IMM32.DLL
0x77520000 - 0x775e8000 C:\Windows\system32\MSCTF.dll
0x75cd0000 - 0x75d7a000 C:\Windows\system32\msvcrt.dll
0x774e0000 - 0x774e9000 C:\Windows\system32\LPK.DLL
0x77090000 - 0x7710d000 C:\Windows\system32\USP10.dll
0x7c340000 - 0x7c396000 C:\Program Files\Java\jre6\bin\msvcr71.dll
0x6d7f0000 - 0x6da96000 C:\Program Files\Java\jre6\bin\client\jvm.dll
0x74a60000 - 0x74a92000 C:\Windows\system32\WINMM.dll
0x77240000 - 0x77385000 C:\Windows\system32\ole32.dll
0x76e20000 - 0x76ead000 C:\Windows\system32\OLEAUT32.dll
0x74800000 - 0x7483e000 C:\Windows\system32\OLEACC.dll
0x75a20000 - 0x75a4c000 C:\Windows\system32\apphelp.dll
0x6d7a0000 - 0x6d7ac000 C:\Program Files\Java\jre6\bin\verify.dll
0x6d320000 - 0x6d33f000 C:\Program Files\Java\jre6\bin\java.dll
0x6d280000 - 0x6d288000 C:\Program Files\Java\jre6\bin\hpi.dll
0x75be0000 - 0x75be7000 C:\Windows\system32\PSAPI.DLL
0x6d370000 - 0x6d399000 C:\Program Files\Java\jre6\bin\jdwp.dll
0x6d690000 - 0x6d696000 C:\Program Files\Java\jre6\bin\npt.dll
0x6d7e0000 - 0x6d7ef000 C:\Program Files\Java\jre6\bin\zip.dll
0x6d200000 - 0x6d207000 C:\Program Files\Java\jre6\bin\dt_socket.dll
0x774f0000 - 0x7751d000 C:\Windows\system32\WS2_32.dll
0x774d0000 - 0x774d6000 C:\Windows\system32\NSI.dll
0x748e0000 - 0x748ef000 C:\Windows\system32\NLAapi.dll
0x75600000 - 0x75619000 C:\Windows\system32\IPHLPAPI.DLL
0x75410000 - 0x75445000 C:\Windows\system32\dhcpcsvc.DLL
0x756d0000 - 0x756fc000 C:\Windows\system32\DNSAPI.dll
0x75a80000 - 0x75a94000 C:\Windows\system32\Secur32.dll
0x75640000 - 0x75647000 C:\Windows\system32\WINNSI.DLL
0x753e0000 - 0x75402000 C:\Windows\system32\dhcpcsvc6.DLL
0x72d40000 - 0x72d4f000 C:\Windows\system32\napinsp.dll
0x72d00000 - 0x72d12000 C:\Windows\system32\pnrpnsp.dll
0x75230000 - 0x7526b000 C:\Windows\System32\mswsock.dll
0x72d30000 - 0x72d38000 C:\Windows\System32\winrnr.dll
0x76eb0000 - 0x76ef9000 C:\Windows\system32\WLDAP32.dll
0x72d20000 - 0x72d2c000 C:\Windows\system32\wshbth.dll
0x76f00000 - 0x7708a000 C:\Windows\system32\SETUPAPI.dll
0x73580000 - 0x73586000 C:\Windows\system32\rasadhlp.dll
0x74f00000 - 0x74f05000 C:\Windows\System32\wshtcpip.dll
0x6d000000 - 0x6d14a000 C:\Program Files\Java\jre6\bin\awt.dll
0x72cb0000 - 0x72cf2000 C:\Windows\system32\WINSPOOL.DRV
0x74b60000 - 0x74cfe000 C:\Windows\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.6002.18305_none_5cb72f2a088b0ed3\COMCTL32.dll
0x76ad0000 - 0x76b29000 C:\Windows\system32\SHLWAPI.dll
0x750d0000 - 0x7510b000 C:\Windows\system32\rsaenh.dll
0x75aa0000 - 0x75abe000 C:\Windows\system32\USERENV.dll
0x6d600000 - 0x6d613000 C:\Program Files\Java\jre6\bin\net.dll
0x75320000 - 0x75325000 C:\Windows\System32\wship6.dll
0x184e0000 - 0x18552000 C:\Users\jiangq\AppData\Local\Temp\jna\jna1195621861765249770.dll
0x69b90000 - 0x69b97000 C:\workspace\jnatester\dlls\CVClient_DLL_C_Wrapper.dll
0x18620000 - 0x187f3000 C:\workspace\jnatester\dlls\cvclient.dll
0x75eb0000 - 0x769c1000 C:\Windows\system32\SHELL32.dll
0x69a70000 - 0x69b13000 C:\Windows\WinSxS\x86_microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.30729.1_none_e163563597edeada\MSVCR90.dll
0x692f0000 - 0x6937e000 C:\Windows\WinSxS\x86_microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.30729.1_none_e163563597edeada\MSVCP90.dll
0x758f0000 - 0x75966000 C:\Windows\system32\NETAPI32.dll

VM Arguments:
jvm_args: -agentlib:jdwp=transport=dt_socket,suspend=y,address=localhost:55173 -Djna.library.path=C:\workspace\jnatester\dlls -Djna.dump.memory=true -Dfile.encoding=Cp1252 
java_command: CVClientTester
Launcher Type: SUN_STANDARD

Environment Variables:
JAVA_HOME=C:\Program Files\Java\jee6\jdk
CLASSPATH=.;C:\Program Files\Java\jre6\lib\ext\QTJava.zip
PATH=C:/Program Files/Java/jre6/bin/client;C:/Program Files/Java/jre6/bin;C:/Program Files/Java/jre6/lib/i386;C:\Program Files\Xuggle\bin;C:\Program Files\Common Files\Microsoft Shared\Windows Live;C:\Program Files\RA2HP\;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Program Files\ActivIdentity\ActivClient\;C:\Program Files\Borland\StarTeam SDK 10.4\Lib;C:\Program Files\Borland\StarTeam SDK 10.4\Bin;c:\Program Files\Microsoft SQL Server\100\Tools\Binn\;c:\Program Files\Microsoft SQL Server\100\DTS\Binn\;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Program Files\Java\jre6\bin;C:\Program Files\The Open Group\WMI Mapper\bin;C:\Program Files\QuickTime\QTSystem\;C:\MinGW\bin;C:\Program Files\Common Files\Microsoft Shared\Windows Live;c:\ant\bin;C:\Program Files\Java\jee6\bin;C:\Program Files\Java\jee6\jdk\bin
USERNAME=jiangq
OS=Windows_NT
PROCESSOR_IDENTIFIER=x86 Family 6 Model 37 Stepping 5, GenuineIntel



---------------  S Y S T E M  ---------------

OS: Windows Vista Build 6002 Service Pack 2

CPU:total 4 (2 cores per cpu, 2 threads per core) family 6 model 37 stepping 5, cmov, cx8, fxsr, mmx, sse, sse2, sse3, ssse3, sse4.1, sse4.2, popcnt, ht

Memory: 4k page, physical 3133892k(842200k free), swap 6479760k(2137188k free)

vm_info: Java HotSpot(TM) Client VM (19.1-b02) for windows-x86 JRE (1.6.0_24-b07), built on Feb  2 2011 17:44:41 by "java_re" with MS VC++ 7.1 (VS2003)

time: Wed Mar 21 16:58:18 2012
elapsed time: 150 seconds

Timothy Wall

unread,
Mar 22, 2012, 3:21:06 PM3/22/12
to jna-...@googlegroups.com
hmm... must be an oversight. Native.free() should have a version that takes a Pointer argument.

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

Mike Jiang

unread,
Mar 22, 2012, 3:39:33 PM3/22/12
to jna-...@googlegroups.com
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);

in .cpp file:
CVCLIENT_DLL_C_WRAPPER_API char* CVCWrapperSendCommand(CVCHANDLE CVCSessionHandle, int timeout, int tracing, const char* request)
{
CVCCommand commandCpp;
commandCpp.nTimeout = timeout;
commandCpp.ntracing = tracing;
commandCpp.strXMLCommand = request;

CVCRC rc = CVClientSendCommand(CVCSessionHandle, commandCpp);
    
return strdup1(commandCpp.strXMLResponse.c_str()); 
}

CVCLIENT_DLL_C_WRAPPER_API void freeIt(char *s)
{
return free(s);
}

CVCLIENT_DLL_C_WRAPPER_API char *strdup1(const char *s) {
    char *d = (char*)malloc (strlen (s) + 1);   // Space for length plus nul
    if (d == NULL) return NULL;          // No memory
    strcpy (d,s);                        // Copy the characters
    return d;                            // Return the new string
}

2). in java code, call to freeIt(Pointer p) to free the memory, and now it seemed no memory leak.

public interface CVLib extends Library
{
CVLib INSTANCE = (CVLib) Native.loadLibrary("CVClient_DLL_C_Wrapper", CVLib.class);
void freeIt(Pointer p) ;
                ...
        }

public String sendRequest(String requestString, int timeout, int tracing) throws Throwable
{

command.timeout = timeout;
command.tracing = tracing;
command.request = requestString;

Pointer responsePointer = CVLib.INSTANCE.CVCWrapperSendCommand(clientHandle, command.timeout, command.tracing,
command.request);
final String response = responsePointer.getString(0);
System.out.println("the response in structure is " + response);
CVLib.INSTANCE.freeIt(responsePointer);       //this one invokes the native function to free the memory in heap allocated by calling malloc().
return response;
}

Timothy Wall

unread,
Mar 22, 2012, 4:09:00 PM3/22/12
to jna-...@googlegroups.com

On Mar 22, 2012, at 3:39 PM, Mike Jiang wrote:

> 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*).

Mike Jiang

unread,
Mar 22, 2012, 4:52:45 PM3/22/12
to jna-...@googlegroups.com
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.

Thanks.

Mike Jiang

unread,
Mar 22, 2012, 5:12:33 PM3/22/12
to jna-...@googlegroups.com
Here is a screen snapshot of the dependency tool for C_Wrapper.dll. It is linked to use MSVCR90.dll and MSVCR90.dll. 

Inline image 1


From the crashing dump file, the jna uses,

C  [msvcrt.dll+0x9c03]
0x75cd0000 - 0x75d7a000 C:\Windows\system32\msvcrt.dll
0x69a70000 - 0x69b13000 C:\Windows\WinSxS\x86_microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.30729.1_none_e163563597edeada\MSVCR90.dll
image.png

Timothy Wall

unread,
Mar 22, 2012, 5:29:09 PM3/22/12
to jna-...@googlegroups.com

On Mar 22, 2012, at 4:52 PM, Mike Jiang wrote:

> 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.

Timothy Wall

unread,
Mar 22, 2012, 5:30:10 PM3/22/12
to jna-...@googlegroups.com
That's the cause of the problem, then. You must allocate and free memory using the same runtime. The two can coexist, but you can't allocate with one runtime and free with the other.

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>

Mike Jiang

unread,
Mar 22, 2012, 5:37:23 PM3/22/12
to jna-...@googlegroups.com
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?

Timothy Wall

unread,
Mar 22, 2012, 5:48:21 PM3/22/12
to jna-...@googlegroups.com

On Mar 22, 2012, at 5:37 PM, Mike Jiang wrote:

> 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.

Mike Jiang

unread,
Mar 22, 2012, 5:55:30 PM3/22/12
to jna-...@googlegroups.com
The issue I referred to is the wrapper.dll and jna use different MSVCR90.dlls, I think. 

How can I control the jna to use the MSVCRT and MSVCR90.dll under windows\system32 folder? use the setting -Djna.library.path? I used it like,
-Djna.library.path=dlls;c:\windows\system32

but it still went to a different folder to get the MSVCR71.dll and MSVCR90.dll, resulting in a crashing.

Timothy Wall

unread,
Mar 22, 2012, 6:46:44 PM3/22/12
to jna-...@googlegroups.com
Your best bet is to always do the allocation and deallocation in the same context. Either let JNA allocate/free the memory, or have your wrapper DLL do it (with or without a JNA-triggered access point).

Roman Slavík

unread,
Apr 3, 2012, 3:34:33 PM4/3/12
to jna-...@googlegroups.com
Hi guys,
I have problem with jna. I have C function:

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 :(


Timothy Wall

unread,
Apr 3, 2012, 7:00:31 PM4/3/12
to jna-...@googlegroups.com
Return Pointer and then operate on that value as required (Pointer.getByteArray() or .getCharArray()). JNA cannot automatically convert to a primitive array for you because it does not know the length beforehand.

Mikael

unread,
Mar 15, 2014, 10:10:05 AM3/15/14
to jna-...@googlegroups.com
Mike, how did you solve this problem in the end?  It looks like I have a very similar issue
Reply all
Reply to author
Forward
0 new messages