JNA - Correct Way To Free Memory

1,497 views
Skip to first unread message

Damien Gallagher

unread,
Sep 11, 2017, 4:15:26 PM9/11/17
to Java Native Access
Hi

I have the following code to call a function using jna

    Pointer pointerValue = new Memory(textSizeValue);
   
PointerByReference outputText = new PointerByReference(pointerValue);
    LOGGER
.debug("textSizeValue:{}", textSizeValue);
    returnCode
= conversionInterface.fblGetPageText(pdfPage, outputText);


   
String pageText = outputText.getPointer().getWideString(0);


The native method I am calling is fblGetPageText

I was wondering what is the correct way to free up the memory created for pointerValue? The method is being called correctly but the app is hanging and I believe it is to do with the memory

Thanks
Damien

Damien Gallagher

unread,
Sep 11, 2017, 5:19:48 PM9/11/17
to Java Native Access
I have tried the following but it doesnt seem to work


       
long nativeValue = Pointer.nativeValue(pointerValue);
       
Native.free(nativeValue);

Matthias Bläsing

unread,
Sep 12, 2017, 5:34:14 AM9/12/17
to jna-...@googlegroups.com
Hi Damien,
Memory allocated by an Memory object is automaticly freed, when the corresponding Memory Object is GCed.

The memory object does a plain Native#malloc on construction and calls Native#free on finalization.

But you need to consult the documentation of the library you are using, as the construct looks strange to me. I'm accustomed to seeing PointerByReference when the callee (in this case the fblGetPageText function) allocates the memory and return that. In that case there needs to be a convention how/when this memory needs to be freed.

Oh! And the code above is wrong - it should be:

String pageText = outputText.getValue().getWideString(0);

Else you get the wrong pointer and it should not even work.

You are saying your app hangs. I'll asume the code you present above is not the whole code. I saw something like this with exceptions on the Swing-EDT, which were silently swallowed, until I installed an uncaught exception handler.

I suggest you implement a minimal sample and try to reproduce the problem with that.

HTH

Matthias

Damien Gallagher

unread,
Sep 12, 2017, 5:51:25 AM9/12/17
to Java Native Access
Hi Matthias

Thank you for getting back to me on this

I had a chat with the developer of the library and he has updated the header file

He informs me that it is up to me to manage the memory

Here is a minimal sample of the code
public String getPageText(Pointer pdfPage)
 
{
 
String pageText = null;
 
IntByReference textSizePtr = new IntByReference();
 
Pointer outputValuePtr = null;
 
int returnCode = conversionInterface.fblGetPageText(pdfPage, outputValuePtr, textSizePtr);

 
int textSizeValue = textSizePtr.getValue();
 outputValuePtr
= new Memory(textSizeValue);

 returnCode
= conversionInterface.fblGetPageText(pdfPage, outputValuePtr, textSizePtr);


 pageText
= outputValuePtr.getWideString(0);
 
 outputValuePtr
= null;
 LOGGER
.debug("Exiting getPageText - pageText: {}", pageText);
 
return pageText;
 
}


The first call to fblGetPageText expects a null pointer and returns the size of the pointer to create
Then based on the value of the textSizePtr - I create the pointer for the second call to fblGetPageText

Do you see anything wrong with what I am trying to do here?

Thanks
Damien

Damien Gallagher

unread,
Sep 12, 2017, 11:50:22 AM9/12/17
to Java Native Access
Hi Matthias

Just wondering am I correctly creating the pointer in my code?

Thanks
Damien

Matthias Bläsing

unread,
Sep 12, 2017, 1:09:32 PM9/12/17
to jna-...@googlegroups.com
Hi Damien,

Am Dienstag, den 12.09.2017, 08:50 -0700 schrieb Damien Gallagher:

Just wondering am I correctly creating the pointer in my code?


On Tuesday, September 12, 2017 at 10:51:25 AM UTC+1, Damien Gallagher wrote:

I had a chat with the developer of the library and he has updated the header file

He informs me that it is up to me to manage the memory

Here is a minimal sample of the code
public String getPageText(Pointer pdfPage)
 
{
 
String pageText = null;
 
IntByReference textSizePtr = new IntByReference();
 
Pointer outputValuePtr = null;
 
int returnCode = conversionInterface.fblGetPageText(pdfPage, outputValuePtr, textSizePtr);

 
int textSizeValue = textSizePtr.getValue();
 outputValuePtr
= new Memory(textSizeValue);

 returnCode
= conversionInterface.fblGetPageText(pdfPage, outputValuePtr, textSizePtr);


 pageText
= outputValuePtr.getWideString(0);
 
 outputValuePtr
= null;
 LOGGER
.debug("Exiting getPageText - pageText: {}", pageText);
 
return pageText;
 
}


The first call to fblGetPageText expects a null pointer and returns the size of the pointer to create
Then based on the value of the textSizePtr - I create the pointer for the second call to fblGetPageText

Do you see anything wrong with what I am trying to do here?


This looks good. I'd suggest you run the above code in a stand-alone sample, without threading and fancy stuff. This way you'll see any exceptions/errors that might be raised.

Greetings

Matthias

Damien Gallagher

unread,
Sep 12, 2017, 1:24:34 PM9/12/17
to Java Native Access
Hi Matthias

Just tried that and the code throws some fatal errors
Please see the below console entry and the attached error report

Thanks
Damien
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x76fd14ae, pid=8592, tid=0x00005c54
#
# JRE version: Java(TM) SE Runtime Environment (8.0_144-b01) (build 1.8.0_144-b01)
# Java VM: Java HotSpot(TM) Client VM (25.144-b01 mixed mode windows-x86 )
# Problematic frame:
# C  [ntdll.dll+0x414ae]
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# C:\development\sourceControl\3dissue\3d-issue-canvas\JavaProject\3DIssueCanvas\hs_err_pid8592.log
#
# If you would like to submit a bug report, please visit:
#   http://bugreport.java.com/bugreport/crash.jsp
#
hs_err_pid8592.log

Matthias Bläsing

unread,
Sep 12, 2017, 2:09:37 PM9/12/17
to jna-...@googlegroups.com
Hi Damien,

Am Dienstag, den 12.09.2017, 10:24 -0700 schrieb Damien Gallagher:
>
> Just tried that and the code throws some fatal errors
> Please see the below console entry and the attached error report
>
>
> [Segfault in native Code and without Java stack trace]
>

sorry, without having the source code and the option to run this, I can
only guess.

Greetings

Matthias

Damien Gallagher

unread,
Sep 12, 2017, 2:19:30 PM9/12/17
to jna-...@googlegroups.com
Hi Matthias

Can I put this code on google drive or somewhere and send you a link?

Thanks
Damien


Greetings

Matthias

--
You received this message because you are subscribed to a topic in the Google Groups "Java Native Access" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/jna-users/qM9Y1478cbA/unsubscribe.
To unsubscribe from this group and all its topics, send an email to jna-users+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

mbla...@doppel-helix.eu

unread,
Sep 13, 2017, 4:34:31 AM9/13/17
to Java Native Access

Hi Damien,


Am Dienstag, 12. September 2017 20:19:30 UTC+2 schrieb Damien Gallagher:

Can I put this code on google drive or somewhere and send you a link?


if you can come up with a runnable stand-alone sample I'm willing to have a look.

Greetings

Matthias

Damien Gallagher

unread,
Sep 13, 2017, 4:44:03 AM9/13/17
to Java Native Access
Hi Matthias

I have come up with a solution.
I used jnaerator to generate my interface file and it recommended using a CharBuffer from the java.nio package

I used the CharBuffer instead of the direct pointer and my issues have disappeared.


Here is the latest
public String getPageText(Pointer pdfPage)
 {
 String pageText = null;
 IntByReference textSizePtr = new IntByReference();
 Pointer outputValuePtr = null;
 int returnCode = conversionInterface.fblGetPageText(pdfPage, null, textSizePtr);

 int textSizeValue = textSizePtr.getValue();
 CharBuffer outputValuePtr = CharBuffer.allocate(textSizeValue);
 
 returnCode = conversionInterface.fblGetPageText(pdfPage, outputValuePtr, textSizePtr);

 pageText = charBufferTextOutputValue.toString();
 

 LOGGER.debug("Exiting getPageText - pageText: {}", pageText);
 return pageText;
 }

Does this look ok to you?

Thanks
Damien

Matthias Bläsing

unread,
Sep 13, 2017, 6:41:11 AM9/13/17
to jna-...@googlegroups.com
Hi Damien,

Am Mittwoch, den 13.09.2017, 01:44 -0700 schrieb Damien Gallagher:
>
> I used jnaerator to generate my interface file and it recommended using a CharBuffer from the java.nio package
>
> I used the CharBuffer instead of the direct pointer and my issues have disappeared.
>
>
> Here is the latest
> public String getPageText(Pointer pdfPage)
>  {
>  String pageText = null;
>  IntByReference textSizePtr = new IntByReference();
>  Pointer outputValuePtr = null;
>  int returnCode = conversionInterface.fblGetPageText(pdfPage, null, textSizePtr);
>
>  int textSizeValue = textSizePtr.getValue();
>  CharBuffer outputValuePtr = CharBuffer.allocate(textSizeValue);
>  
>  returnCode = conversionInterface.fblGetPageText(pdfPage, outputValuePtr, textSizePtr);
>
>  pageText = charBufferTextOutputValue.toString();
>  
>
>  LOGGER.debug("Exiting getPageText - pageText: {}", pageText);
>  return pageText;
>  }

yes and I also now see the difference to your previous code:

> int textSizeValue = textSizePtr.getValue();
> outputValuePtr = new Memory(textSizeValue);

> returnCode = conversionInterface.fblGetPageText(pdfPage, outputValuePtr, textSizePtr);

The difference is the allocated memory size - from the doc:

public static CharBuffer allocate(int capacity)
capacity - The new buffer's capacity, in chars

The important part is "in chars", so this basicly allocates a memory buffer of 2 * chars bytes (a char is 16 bit).

Your input signature was:

int getText(void* page, wchar_t*& pTextOut);

A wchar_t has a platform dependend width, but is in the range of 16-32 bit. So if you modify the code above to:

> int textSizeValue = textSizePtr.getValue();
> outputValuePtr = new Memory(textSizeValue * 4);

> returnCode = conversionInterface.fblGetPageText(pdfPage, outputValuePtr, textSizePtr);

it should also work. This assumes, that textSizePtr is the returned character count and not required byte count.

HTH

Matthias

Damien Gallagher

unread,
Sep 13, 2017, 10:45:24 AM9/13/17
to Java Native Access
Hi Matthias

Yes that has worked a treat by setting the memory to be the textSize by 4

Thank you so much for your help on this particular item

Regards
Damien

Timothy Wall

unread,
Sep 14, 2017, 12:35:23 AM9/14/17
to jna-...@googlegroups.com
Use Native.WCHAR_SIZE to determine the size of wchar_t.

--
You received this message because you are subscribed to the Google Groups "Java Native Access" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jna-users+unsubscribe@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages