JNI memory leak??

Discussion in 'Java' started by Jim, Sep 23, 2005.

  1. Jim

    Jim Guest

    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
    Jim, Sep 23, 2005
    #1
    1. Advertising

  2. 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
    Gordon Beaton, Sep 24, 2005
    #2
    1. Advertising

  3. 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
    Gordon Beaton, Sep 24, 2005
    #3
  4. Jim

    Wibble Guest

    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)
    Wibble, Sep 24, 2005
    #4
  5. Jim

    Jim Guest

    "Wibble" <> wrote in message
    news:...
    > 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.
    Jim, Sep 24, 2005
    #5
  6. Jim

    Wibble Guest

    Jim wrote:
    > "Wibble" <> wrote in message
    > news:...
    >
    >>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().
    Wibble, Sep 24, 2005
    #6
  7. Jim

    Jim Guest

    "Wibble" <> wrote in message
    news:...
    > Jim wrote:
    > > "Wibble" <> wrote in message
    > > news:...
    > >
    > >>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.
    Jim, Sep 24, 2005
    #7
  8. Jim

    Chris Uppal Guest

    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
    Chris Uppal, Sep 25, 2005
    #8
  9. Jim

    zakkir

    Joined:
    Nov 14, 2009
    Messages:
    1
    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.
    zakkir, Nov 14, 2009
    #9
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. s.subbarayan

    Dynamic memory allocation and memory leak...

    s.subbarayan, Mar 18, 2005, in forum: C Programming
    Replies:
    10
    Views:
    697
    Eric Sosman
    Mar 22, 2005
  2. Richard Heathfield

    Leak or no leak ??

    Richard Heathfield, Jul 10, 2006, in forum: C Programming
    Replies:
    4
    Views:
    349
    Richard Heathfield
    Jul 10, 2006
  3. cham
    Replies:
    5
    Views:
    767
  4. cornerback
    Replies:
    0
    Views:
    1,189
    cornerback
    Aug 28, 2009
  5. Mark Probert
    Replies:
    4
    Views:
    325
    Mark Probert
    Feb 9, 2005
Loading...

Share This Page