wchar_t** to Java String conversion

629 views
Skip to first unread message

jennifer

unread,
Nov 4, 2011, 4:18:11 PM11/4/11
to Java Native Access
Hi,

I have C function which passes in a wchar_t** parameter to Java.
In Java I create a new PointerByReference, pass it in as the parameter
when calling the C function and then use getValue().getString(0, true)
to get the data as a Java string.

It works well for short strings up to about 140 000 characters - once
the strings get much longer than that, the JVM crashes in the JNA
dispatch.c code in the newJavaString function.

Are there known limits for the size of strings that can be passed
around this way? Or should I be doing something differently to handle
wchar_t** to Java String conversions?

Thanks,
Jennifer

SoothingMist

unread,
Nov 4, 2011, 4:52:15 PM11/4/11
to Java Native Access
Jennifer: Which JVM are you using? They are not all created equal.

You may end up splitting your strings into different buffers.

Timothy Wall

unread,
Nov 4, 2011, 5:03:10 PM11/4/11
to jna-...@googlegroups.com
What OS/CPU/VM?

On platforms with sizeof(wchar_t) == 4, newJavaString attempts to alloca() temporary memory in order to copy the larger-sized values into Java jchar. It's possible that this call may be failing (which is a bug, since it should throw OOM on failure rather than crashing).

jennifer

unread,
Nov 7, 2011, 11:49:32 AM11/7/11
to Java Native Access
I'm using CentOS on an AMD Phenom(tm) II X6 1035T Processor with Sun's
VM.

Timothy Wall

unread,
Nov 7, 2011, 12:47:52 PM11/7/11
to jna-...@googlegroups.com
I ran some tests on this and got varying errors on different platforms. I've checked in some fixes to avoid overly large alloca calls (which seem to succeed but result in crashes when the memory is actually used), but you might consider breaking the string into smaller chunks. The current implementation has to convert the native 4-byte wchar_t into 2-byte Java character, and uses a buffer the full size of the string in order to store the temporary conversion.

Normally, Pointer.getString(0, true) is the appropriate method for extracting a string.

As a workaround, Pointer.indexOf(offset, value) can help find the string's nul terminator (but note that it looks for a single zero byte; you will need to look for N zero bytes in a row starting at a multiple of N, where N == Pointer.WCHAR_SIZE. Once you determine the native string length, you can use a StringBuffer to build up the string by extracting smaller chunks of char[] instead of reading all out at once.

jennifer

unread,
Nov 7, 2011, 1:17:14 PM11/7/11
to Java Native Access
Okay great - thanks I'll try using a StringBuffer.
Reply all
Reply to author
Forward
0 new messages