Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Java > Can't allocate large char array in JNI

Reply
Thread Tools

Can't allocate large char array in JNI

 
 
CD1
Guest
Posts: n/a
 
      04-21-2008
Hi there!

I'm trying to allocate a char array using JNI, but when the length is
too big it doesn't work! My char array is a representation of an
image, and its size is the width * height * 3 characters, so it
usually goes beyond 1 MB. My code works with smaller images, but when
the array size is bigger than 718832 (don't know why this is the
maximum value), the JVM crashes and it returns 134 as the exit code.

My code is like this:

// the variables are JNIEnv *env, int length, jchar *value, jmethodID
char_array_fid

jcharArray jchar_array = (*env)->NewCharArray(env, length);
if (jchar_array == NULL) {
return;
}
(*env)->SetCharArrayRegion(env, jchar_array, 0, length, value); // !!!
(*env)->SetObjectField(env, obj, char_array_fid, jchar_array);

By using printfs, I've found out the JVM crashes when it calls the
function SetCharArrayRegion, but only if the length is greater than
718832. And if I modify the length value to something like 1000, this
exact code works fine.

Any help would be appreciated

See ya!
 
Reply With Quote
 
 
 
 
Gordon Beaton
Guest
Posts: n/a
 
      04-21-2008
On Sun, 20 Apr 2008 20:07:48 -0700 (PDT), CD1 wrote:
> My code is like this:


Code that's "like" yours doesn't help anyone debug your real code.

> // the variables are JNIEnv *env, int length, jchar *value, jmethodID
> char_array_fid
>
> jcharArray jchar_array = (*env)->NewCharArray(env, length);
> if (jchar_array == NULL) {
> return;
> }
> (*env)->SetCharArrayRegion(env, jchar_array, 0, length, value); // !!!
> (*env)->SetObjectField(env, obj, char_array_fid, jchar_array);
>
> By using printfs, I've found out the JVM crashes when it calls the
> function SetCharArrayRegion, but only if the length is greater than
> 718832. And if I modify the length value to something like 1000, this
> exact code works fine.
>
> Any help would be appreciated


Try posting a compilable example or at least a complete function. The
problem is usually in the parts you didn't post.

How many jchars are in the "jchar *value" array that you pass to
SetCharArrayRegion? Perhaps more importantly, how did you allocate and
initialize it?

What does (*env)->ExceptionOccurred(env) (and ExceptionDescribe()) say
after the call to SetCharArrayRegion()? After SetObjectField()?

/gordon

--
 
Reply With Quote
 
 
 
 
CD1
Guest
Posts: n/a
 
      04-21-2008
Hi Gordon,

Sorry for the lack of details. Here's the full code:

// start here

jobject new0(JNIEnv *env, jclass cls) {
jmethodID constructor_mid = (*env)->GetMethodID(env, cls,
"<init>", "()V");
if (constructor_mid == NULL) {
return NULL;
}
return (*env)->NewObject(env, cls, constructor_mid);
}

void set_int(JNIEnv *env, jclass cls, jobject obj,
char *field_name, jint value) {
jfieldID int_fid = (*env)->GetFieldID(env, cls, field_name, "I");
if (int_fid == NULL) {
return;
}
(*env)->SetIntField(env, obj, int_fid, value);
}

void set_char_array(JNIEnv *env, jclass cls, jobject obj,
char *field_name, jchar *value, int length) {
jfieldID char_array_fid = (*env)->GetFieldID(env, cls, field_name,
"[C");
if (char_array_fid == NULL) {
return;
}
jcharArray jchar_array = (*env)->NewCharArray(env, length);
if (jchar_array == NULL) {
return;
}
(*env)->SetCharArrayRegion(env, jchar_array, 0, length, value);
(*env)->ExceptionDescribe(env);
(*env)->SetObjectField(env, obj, char_array_fid, jchar_array);
}

JNIEXPORT jobject JNICALL Java_OpenCv_loadImage(JNIEnv *env, jclass
jclazz,
jstring jfilePath) {
const char *file_path = (*env)->GetStringUTFChars(env, jfilePath,
NULL);
IplImage *cv_image = cvLoadImage(file_path, CV_LOAD_IMAGE_COLOR);
(*env)->ReleaseStringUTFChars(env, jfilePath, file_path);
if (cv_image == NULL) {
return NULL;
}
jclass iplimage_cls = (*env)->FindClass(env, "IplImage");
if (iplimage_cls == NULL) {
return NULL;
}
jobject jiplimage = new0(env, iplimage_cls);
if (jiplimage == NULL) {
return NULL;
}
set_int(env, iplimage_cls, jiplimage,
"nChannels", (jint) cv_image->nChannels);
if ((*env)->ExceptionCheck(env)) {
return NULL;
}
set_int(env, iplimage_cls, jiplimage, "depth", (jint) cv_image-
>depth);

if ((*env)->ExceptionCheck(env)) {
return NULL;
}
set_int(env, iplimage_cls, jiplimage, "width", (jint) cv_image-
>width);

if ((*env)->ExceptionCheck(env)) {
return NULL;
}
set_int(env, iplimage_cls, jiplimage, "height", (jint) cv_image-
>height);

if ((*env)->ExceptionCheck(env)) {
return NULL;
}
set_char_array(env, iplimage_cls, jiplimage, "imageData",
(jchar *) cv_image->imageData, cv_image->imageSize);
if ((*env)->ExceptionCheck(env)) {
return NULL;
}
set_int(env, iplimage_cls, jiplimage,
"dataOrder", (jint) cv_image->dataOrder);
if ((*env)->ExceptionCheck(env)) {
return NULL;
}
set_int(env, iplimage_cls, jiplimage, "origin", (jint) cv_image-
>origin);

if ((*env)->ExceptionCheck(env)) {
return NULL;
}
set_int(env, iplimage_cls, jiplimage,
"widthStep", (jint) cv_image->widthStep);
if ((*env)->ExceptionCheck(env)) {
return NULL;
}
set_int(env, iplimage_cls, jiplimage,
"imageSize", (jint) cv_image->imageSize);
if ((*env)->ExceptionCheck(env)) {
return NULL;
}
set_char_array(env, iplimage_cls, jiplimage, "imageDataOrigin",
(jchar *) cv_image->imageDataOrigin,
cv_image->width * cv_image->height * cv_image->nChannels);
set_int(env, iplimage_cls, jiplimage, "align", (jint) cv_image-
>align);

if ((*env)->ExceptionCheck(env)) {
return NULL;
}
cvReleaseImage(&cv_image);
return jiplimage;
}

// end here

The jchar *value comes from the object allocated by the library
OpenCV, ant its size is the imageSize field of the IplImage struct.

When I run this function passing a small image, it always works; with
a medium image, it works sometimes (I run once and it works, I run
again and it doesn't!); but with a large image (specifically,
imageSize = 1434600), it never worked: the JVM crashes right on the
SetCharArrayRegion call, so the ExceptionDescribe in the line below is
never reached. So, based on this randomness I suppose the problem is
memory related, I don't know ;/

The header of the JVM crash log is this:

#
# An unexpected error has been detected by Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x00002ae7f37b1cc7, pid=16200, tid=1076017488
#
# Java VM: Java HotSpot(TM) 64-Bit Server VM (10.0-b22 mixed mode
linux-amd64)
# Problematic frame:
# C [libc.so.6+0x75cc7] memcpy+0x3f7
#
# If you would like to submit a bug report, please visit:
# http://java.sun.com/webapps/bugreport/crash.jsp
#

The purpose of this function, by the way, is to convert a C structure
(IplImage) to a Java object with the same attributes so it can be
parsed on the Java side.

Thanks again!

On Apr 21, 4:12 am, Gordon Beaton <(E-Mail Removed)> wrote:
> On Sun, 20 Apr 2008 20:07:48 -0700 (PDT), CD1 wrote:
> > My code is like this:

>
> Code that's "like" yours doesn't help anyone debug your real code.
>
>
>
> > // the variables are JNIEnv *env, int length, jchar *value, jmethodID
> > char_array_fid

>
> > jcharArray jchar_array = (*env)->NewCharArray(env, length);
> > if (jchar_array == NULL) {
> > return;
> > }
> > (*env)->SetCharArrayRegion(env, jchar_array, 0, length, value); // !!!
> > (*env)->SetObjectField(env, obj, char_array_fid, jchar_array);

>
> > By using printfs, I've found out the JVM crashes when it calls the
> > function SetCharArrayRegion, but only if the length is greater than
> > 718832. And if I modify the length value to something like 1000, this
> > exact code works fine.

>
> > Any help would be appreciated

>
> Try posting a compilable example or at least a complete function. The
> problem is usually in the parts you didn't post.
>
> How many jchars are in the "jchar *value" array that you pass to
> SetCharArrayRegion? Perhaps more importantly, how did you allocate and
> initialize it?
>
> What does (*env)->ExceptionOccurred(env) (and ExceptionDescribe()) say
> after the call to SetCharArrayRegion()? After SetObjectField()?
>
> /gordon
>
> --


 
Reply With Quote
 
Gordon Beaton
Guest
Posts: n/a
 
      04-22-2008
On Mon, 21 Apr 2008 08:07:08 -0700 (PDT), CD1 wrote:
> The jchar *value comes from the object allocated by the library
> OpenCV, ant its size is the imageSize field of the IplImage struct.


What is the real declared type of the cv_image->imageData, i.e. before
the explicit typecast?

What are "sizeof(jchar)" and "sizeof(cv_image->imageData[0])"?

Here's something you can test, add this to the start of set_char_array()
before calling any of the jni functions:

volatile jchar tmp;
int i;

for (i=0; i<length; i++) {
tmp = value[i];
}

Does this code pass ok?

Try a small example without using your image library. With the
following code I can successfully allocate char arrays of 30MB using
the default java heap size. Beyond that, ExceptionDescribe() correctly
identifies the error as "Out of memory: Java heap space":

// public static native char[] getCharArray(int n);

JNIEXPORT jcharArray JNICALL
Java_Chars_getCharArray(JNIEnv *env, jclass unused, jint n)
{
jcharArray jca;
jchar *jc;
int i;

jca = (*env)->NewCharArray(env, n);

if ((*env)->ExceptionOccurred(env)) {
(*env)->ExceptionDescribe(env);
}

if ((jc = malloc(n * sizeof(jchar)))) {
// some nonsense initial values
for (i=0; i<n; i++) {
jc[i] = i % 255;
}

(*env)->SetCharArrayRegion(env, jca, 0, n, jc);

if ((*env)->ExceptionOccurred(env)) {
(*env)->ExceptionDescribe(env);
}

free(jc);
}

return jca;
}

/gordon

--
 
Reply With Quote
 
Roedy Green
Guest
Posts: n/a
 
      04-22-2008
On Sun, 20 Apr 2008 20:07:48 -0700 (PDT), CD1
<(E-Mail Removed)> wrote, quoted or indirectly quoted someone
who said :

>By using printfs, I've found out the JVM crashes when it calls the
>function SetCharArrayRegion, but only if the length is greater than
>718832. And if I modify the length value to something like 1000, this
>exact code works fine.


Are C strings limited to 64K?
Perhaps you want a byte array. Java chars are 16 bits. C chars are
usually 8 bits.
--

Roedy Green Canadian Mind Products
The Java Glossary
http://mindprod.com
 
Reply With Quote
 
Gordon Beaton
Guest
Posts: n/a
 
      04-22-2008
On 22 Apr 2008 05:46:23 GMT, Gordon Beaton wrote:
> What is the real declared type of the cv_image->imageData, i.e. before
> the explicit typecast?
>
> What are "sizeof(jchar)" and "sizeof(cv_image->imageData[0])"?


Checked this myself: IplImage->imageSize is "image size in bytes", and
IplImage->imageData is a byte pointer (C char), so by casting to a
(jchar*) without adjusting the length, you are exceeding the bounds of
the imageData array by a factor 2.

You should be using a jbyteArray instead. Always treat explicit
typecasts with suspicion...

/gordon

--
 
Reply With Quote
 
CD1
Guest
Posts: n/a
 
      04-24-2008
Thank you guys, that was really the problem! In C, it's a char array,
but in Java it must be a byte array, because of the sizes.

See ya!

On Apr 22, 5:49 am, Gordon Beaton <(E-Mail Removed)> wrote:
> On 22 Apr 2008 05:46:23 GMT, Gordon Beaton wrote:
>
> > What is the real declared type of the cv_image->imageData, i.e. before
> > the explicit typecast?

>
> > What are "sizeof(jchar)" and "sizeof(cv_image->imageData[0])"?

>
> Checked this myself: IplImage->imageSize is "image size in bytes", and
> IplImage->imageData is a byte pointer (C char), so by casting to a
> (jchar*) without adjusting the length, you are exceeding the bounds of
> the imageData array by a factor 2.
>
> You should be using a jbyteArray instead. Always treat explicit
> typecasts with suspicion...
>
> /gordon
>
> --


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Good or best way to allocate a large array Ralph Shnelvar Ruby 44 01-07-2010 03:01 AM
JNI allocate array of arrays of primitive Bill Medland Java 1 10-26-2006 03:28 AM
(const char *cp) and (char *p) are consistent type, (const char **cpp) and (char **pp) are not consistent lovecreatesbeauty C Programming 1 05-09-2006 08:01 AM
Problem- strcat with char and char indexed from char array aldonnelley@gmail.com C++ 3 04-20-2006 07:32 AM
/usr/bin/ld: ../../dist/lib/libjsdombase_s.a(BlockGrouper.o)(.text+0x98): unresolvable relocation against symbol `std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostre silverburgh.meryl@gmail.com C++ 3 03-09-2006 12:14 AM



Advertisments