Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Java > JNI memory leak??

Reply
Thread Tools

JNI memory leak??

 
 
Jim
Guest
Posts: n/a
 
      09-23-2005
I have the code below in a JNI interface routine. If I run it as below (#if
0), then it does not leak memory.
If I change the #if 0 to #if 1, then it leaks - the JVM just keeps on
growing.
I think I am doing all the right things as far as freeing up the bytearray,
etc - at least according to the book.
Anyone please, do you spot a problem?

Thanks,

void *str;

putt.opts = env->GetIntField( obj, put_opts_fid );
putt.timeout = env->GetIntField( obj, put_timeout_fid );
putt.len = env->GetIntField( obj, put_len_fid );
#if 0
jb = (jbyteArray)env->GetObjectField( obj, put_data_fid );
putt.buf = env->GetByteArrayElements( jb, NULL );
#else
str = malloc( putt.len );
memset( (void *)str, 'a', putt.len);
putt.buf = (void *)str;
#endif
if ( putt.buf ) {
rc = sendthedata( hh, &putt );
}
#if 0
env->ReleaseByteArrayElements( jb, (signed char *)putt.buf, 0 );
env->DeleteLocalRef( jb );
#else
free( str );
#endif
return( rc );

Thanks

Jim


 
Reply With Quote
 
 
 
 
Gordon Beaton
Guest
Posts: n/a
 
      09-24-2005
On Fri, 23 Sep 2005 17:41:48 -0400, Jim wrote:
> I have the code below in a JNI interface routine. If I run it as
> below (#if 0), then it does not leak memory.
>
> If I change the #if 0 to #if 1, then it leaks - the JVM just keeps
> on growing.


jb is not an object reference, and you absolutely should not be
calling DeleteLocalRef() on it (in fact in most cases you don't need
to use DeleteLocalRef() at all, even for object references).

I can't say for sure that this is exactly the problem you're seeing,
but it's a problem that could be causing some erratic behaviour in the
JVM.

/gordon


--
[ do not email me copies of your followups ]
g o r d o n + n e w s @ b a l d e r 1 3 . s e
 
Reply With Quote
 
 
 
 
Gordon Beaton
Guest
Posts: n/a
 
      09-24-2005
On 24 Sep 2005 10:08:20 +0200, Gordon Beaton wrote:
> jb is not an object reference


Sorry, I take it all back (I misread the code).

/gordon

--
[ do not email me copies of your followups ]
g o r d o n + n e w s @ b a l d e r 1 3 . s e
 
Reply With Quote
 
Wibble
Guest
Posts: n/a
 
      09-24-2005
Jim wrote:
> I have the code below in a JNI interface routine. If I run it as below (#if
> 0), then it does not leak memory.
> If I change the #if 0 to #if 1, then it leaks - the JVM just keeps on
> growing.
> I think I am doing all the right things as far as freeing up the bytearray,
> etc - at least according to the book.
> Anyone please, do you spot a problem?
>
> Thanks,
>
> void *str;
>
> putt.opts = env->GetIntField( obj, put_opts_fid );
> putt.timeout = env->GetIntField( obj, put_timeout_fid );
> putt.len = env->GetIntField( obj, put_len_fid );
> #if 0
> jb = (jbyteArray)env->GetObjectField( obj, put_data_fid );
> putt.buf = env->GetByteArrayElements( jb, NULL );
> #else
> str = malloc( putt.len );
> memset( (void *)str, 'a', putt.len);
> putt.buf = (void *)str;
> #endif
> if ( putt.buf ) {
> rc = sendthedata( hh, &putt );
> }
> #if 0
> env->ReleaseByteArrayElements( jb, (signed char *)putt.buf, 0 );
> env->DeleteLocalRef( jb );
> #else
> free( str );
> #endif
> return( rc );
>
> Thanks
>
> Jim
>
>

Dont pass NULL to, env->GetByteArrayElements( jb, NULL )

use:

jboolean isCopy;
putt.buf = env->GetByteArrayElements( jb, &isCopy )
if (isCopy) free(putt.buf)
 
Reply With Quote
 
Jim
Guest
Posts: n/a
 
      09-24-2005

"Wibble" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> Jim wrote:
> > I have the code below in a JNI interface routine. If I run it as below

(#if
> > 0), then it does not leak memory.
> > If I change the #if 0 to #if 1, then it leaks - the JVM just keeps on
> > growing.
> > I think I am doing all the right things as far as freeing up the

bytearray,
> > etc - at least according to the book.
> > Anyone please, do you spot a problem?
> >
> > Thanks,
> >
> > void *str;
> >
> > putt.opts = env->GetIntField( obj, put_opts_fid );
> > putt.timeout = env->GetIntField( obj, put_timeout_fid );
> > putt.len = env->GetIntField( obj, put_len_fid );
> > #if 0
> > jb = (jbyteArray)env->GetObjectField( obj, put_data_fid );
> > putt.buf = env->GetByteArrayElements( jb, NULL );
> > #else
> > str = malloc( putt.len );
> > memset( (void *)str, 'a', putt.len);
> > putt.buf = (void *)str;
> > #endif
> > if ( putt.buf ) {
> > rc = sendthedata( hh, &putt );
> > }
> > #if 0
> > env->ReleaseByteArrayElements( jb, (signed char *)putt.buf, 0 );
> > env->DeleteLocalRef( jb );
> > #else
> > free( str );
> > #endif
> > return( rc );
> >
> > Thanks
> >
> > Jim
> >
> >

> Dont pass NULL to, env->GetByteArrayElements( jb, NULL )
>
> use:
>
> jboolean isCopy;
> putt.buf = env->GetByteArrayElements( jb, &isCopy )
> if (isCopy) free(putt.buf)



Hmmmm... I don't think that's correct either. Agreed, maybe I should pass
the "&iscopy" to the GetByteArrayElements(), but since I pass 0 to the
ReleaseByteArrayElements(...., 0) - then JVM will free the elements
(putt.buf) for me.

I researched this in great detail and have pretty much determined that I am
doing it correctly (except for above iscopy). I will delve more into
whether it really leaks or not or do I hit so rapidly that gc() doesn't have
time to do it's thing.


 
Reply With Quote
 
Wibble
Guest
Posts: n/a
 
      09-24-2005
Jim wrote:
> "Wibble" <(E-Mail Removed)> wrote in message
> news:(E-Mail Removed)...
>
>>Jim wrote:
>>
>>>I have the code below in a JNI interface routine. If I run it as below

>
> (#if
>
>>>0), then it does not leak memory.
>>>If I change the #if 0 to #if 1, then it leaks - the JVM just keeps on
>>>growing.
>>>I think I am doing all the right things as far as freeing up the

>
> bytearray,
>
>>>etc - at least according to the book.
>>>Anyone please, do you spot a problem?
>>>
>>>Thanks,
>>>
>>>void *str;
>>>
>>> putt.opts = env->GetIntField( obj, put_opts_fid );
>>> putt.timeout = env->GetIntField( obj, put_timeout_fid );
>>> putt.len = env->GetIntField( obj, put_len_fid );
>>> #if 0
>>> jb = (jbyteArray)env->GetObjectField( obj, put_data_fid );
>>> putt.buf = env->GetByteArrayElements( jb, NULL );
>>> #else
>>> str = malloc( putt.len );
>>> memset( (void *)str, 'a', putt.len);
>>> putt.buf = (void *)str;
>>> #endif
>>> if ( putt.buf ) {
>>> rc = sendthedata( hh, &putt );
>>> }
>>> #if 0
>>> env->ReleaseByteArrayElements( jb, (signed char *)putt.buf, 0 );
>>> env->DeleteLocalRef( jb );
>>> #else
>>> free( str );
>>> #endif
>>> return( rc );
>>>
>>>Thanks
>>>
>>>Jim
>>>
>>>

>>
>>Dont pass NULL to, env->GetByteArrayElements( jb, NULL )
>>
>>use:
>>
>>jboolean isCopy;
>>putt.buf = env->GetByteArrayElements( jb, &isCopy )
>>if (isCopy) free(putt.buf)

>
>
>
> Hmmmm... I don't think that's correct either. Agreed, maybe I should pass
> the "&iscopy" to the GetByteArrayElements(), but since I pass 0 to the
> ReleaseByteArrayElements(...., 0) - then JVM will free the elements
> (putt.buf) for me.
>
> I researched this in great detail and have pretty much determined that I am
> doing it correctly (except for above iscopy). I will delve more into
> whether it really leaks or not or do I hit so rapidly that gc() doesn't have
> time to do it's thing.
>
>

You should also use (*env)->ReleaseByteArrayElements(env, buffer, bytes, 0);

not free().
 
Reply With Quote
 
Jim
Guest
Posts: n/a
 
      09-24-2005

"Wibble" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> Jim wrote:
> > "Wibble" <(E-Mail Removed)> wrote in message
> > news:(E-Mail Removed)...
> >
> >>Jim wrote:
> >>
> >>>I have the code below in a JNI interface routine. If I run it as below

> >
> > (#if
> >
> >>>0), then it does not leak memory.
> >>>If I change the #if 0 to #if 1, then it leaks - the JVM just keeps on
> >>>growing.
> >>>I think I am doing all the right things as far as freeing up the

> >
> > bytearray,
> >
> >>>etc - at least according to the book.
> >>>Anyone please, do you spot a problem?
> >>>
> >>>Thanks,
> >>>
> >>>void *str;
> >>>
> >>> putt.opts = env->GetIntField( obj, put_opts_fid );
> >>> putt.timeout = env->GetIntField( obj, put_timeout_fid );
> >>> putt.len = env->GetIntField( obj, put_len_fid );
> >>> #if 0
> >>> jb = (jbyteArray)env->GetObjectField( obj, put_data_fid );
> >>> putt.buf = env->GetByteArrayElements( jb, NULL );
> >>> #else
> >>> str = malloc( putt.len );
> >>> memset( (void *)str, 'a', putt.len);
> >>> putt.buf = (void *)str;
> >>> #endif
> >>> if ( putt.buf ) {
> >>> rc = sendthedata( hh, &putt );
> >>> }
> >>> #if 0
> >>> env->ReleaseByteArrayElements( jb, (signed char *)putt.buf, 0 );
> >>> env->DeleteLocalRef( jb );
> >>> #else
> >>> free( str );
> >>> #endif
> >>> return( rc );
> >>>
> >>>Thanks
> >>>
> >>>Jim
> >>>
> >>>
> >>
> >>Dont pass NULL to, env->GetByteArrayElements( jb, NULL )
> >>
> >>use:
> >>
> >>jboolean isCopy;
> >>putt.buf = env->GetByteArrayElements( jb, &isCopy )
> >>if (isCopy) free(putt.buf)

> >
> >
> >
> > Hmmmm... I don't think that's correct either. Agreed, maybe I should

pass
> > the "&iscopy" to the GetByteArrayElements(), but since I pass 0 to the
> > ReleaseByteArrayElements(...., 0) - then JVM will free the elements
> > (putt.buf) for me.
> >
> > I researched this in great detail and have pretty much determined that I

am
> > doing it correctly (except for above iscopy). I will delve more into
> > whether it really leaks or not or do I hit so rapidly that gc() doesn't

have
> > time to do it's thing.
> >
> >

> You should also use (*env)->ReleaseByteArrayElements(env, buffer, bytes,

0);
>
> not free().


Yes, for sure. Not doing the ReleaseByte..... definitely leaks.


 
Reply With Quote
 
Chris Uppal
Guest
Posts: n/a
 
      09-25-2005
Jim wrote:

> I have the code below in a JNI interface routine. If I run it as below
> (#if 0), then it does not leak memory.
> If I change the #if 0 to #if 1, then it leaks - the JVM just keeps on
> growing.


I don't know if this will help any, but as far as I can see the code you have
shown is exactly correct. (At least, on the assumption that the lack of error
checking is because you have not reproduced it here for clarity)

I have just run my equivalent of your code in a loop 1 million times, grabbing
the bytes from a 17000 element byte[] (intentionally not a very round number)
and saw no evidence of memory leakage. This was on the JDK 1.5 client JVM,
running over WinXP.

-- chris


 
Reply With Quote
 
zakkir zakkir is offline
Junior Member
Join Date: Nov 2009
Posts: 1
 
      11-14-2009
I am seeing a similar behaviour of memory growth in solaris environment for a similar JNI interface. I would like to know whether the root cause for this problem has been found.

In our case we found the problem disappearing when we finally reset a variable to NULL.
 
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
JNI thread vs. native thread vs. JNI call bgabrhelik Java 0 09-29-2009 03:33 PM
Re: JNI: Error loading DLL from JNI DDL vasanth Java 0 01-25-2005 11:03 AM
Re: JNI: Error loading DLL from JNI DDL vasanth Java 0 01-25-2005 11:01 AM
Porting JNI Windows under JNI LINUX + Wine ? Pasturel Jean-Louis Java 5 03-03-2004 07:50 PM
IBM's JNI fails where Sun's JNI works Alex Hunsley Java 4 11-04-2003 10:34 AM



Advertisments