JNI memory leak??

J

Jim

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
 
G

Gordon Beaton

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
 
W

Wibble

Jim said:
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)
 
J

Jim

Wibble said:
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.
 
W

Wibble

Jim said:
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().
 
J

Jim

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

not free().

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

Chris Uppal

Jim said:
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
 
Joined
Nov 14, 2009
Messages
1
Reaction score
0
did you find what is the problem

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

Forum statistics

Threads
473,995
Messages
2,570,226
Members
46,815
Latest member
treekmostly22

Latest Threads

Top