1

I am using C library from JAVA by calling it through JNI. I've noticed that memory size constantly increasing and decided check memory leaks using valgrind.

This is my fragment of the code which got called from Java.

JNIEXPORT jstring JNICALL Java_GenderService_genderize
  (JNIEnv *env, jobject obj, jstring string)
{
     const char *str = (*env)->GetStringUTFChars(env, string, 0);
     char cap[128];
     strcpy(cap, str);
     (*env)->ReleaseStringUTFChars(env, string, str);

     int gender = get_gender_utf8 (cap,
              GENDER_COMPARE_EXPANDED_UMLAUTS, GENDER_DEFAULT_COUNTRY);

     char* s;
switch (gender)
    {
      case IS_FEMALE        :  s = "FEMALE";            break;
      case IS_MOSTLY_FEMALE :  s = "MOSTLY_FEMALE";     break;
      case IS_MALE          :  s = "MALE";              break;
      case IS_MOSTLY_MALE   :  s = "MOSTLY_MALE";       break;
      case IS_A_COUPLE      :  s = "COUPLE";            break;
      case IS_UNISEX_NAME   :  s = "UNISEX";        break;

      case EQUIVALENT_NAMES :  s = "names are equivalent"; break;
      case NOT_EQUAL_NAMES  :  s = "names are not equal";  break;
      case NAME_NOT_FOUND   :  s = "NAME_NOT_FOUND";       break;
      case ERROR_IN_NAME    :  s = "ERROR_IN_NAME";        break;

      case INTERNAL_ERROR_GENDER :  s = "INTERNAL_ERROR";  break;
      default                    :  s = "UNKNOWN_ERROR";   break;
    }

     return (*env)->NewStringUTF(env, s);
}

Independently I've tested get_gender_utf8() method, by wrapping it in main() and invoking with valgrind, resulted as no leaks were found.

int main (int argc, char *argv[])
{

    char cap[128];
    strcpy(cap, argv[1]);

    int i = get_gender_utf8 (cap,
              GENDER_COMPARE_EXPANDED_UMLAUTS, GENDER_DEFAULT_COUNTRY);

    printf("%d", i);
    char* s;
    s = "FEMALE";
  return (0);
}

=

valgrind --tool=memcheck --leak-check=full ./a.out Dan

65368== Memcheck, a memory error detector
==65368== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==65368== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==65368== Command: ./a.out Dan
==65368==
63==65368==
==65368== HEAP SUMMARY:
==65368==     in use at exit: 0 bytes in 0 blocks
==65368==   total heap usage: 1 allocs, 1 frees, 568 bytes allocated
==65368==
==65368== All heap blocks were freed -- no leaks are possible
==65368==
==65368== For counts of detected and suppressed errors, rerun with: -v
==65368== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 6)

=

Does that mean that leak is somewhere in these lines?

const char *str = (*env)->GetStringUTFChars(env, string, 0);
char cap[128];
strcpy(cap, str);
(*env)->ReleaseStringUTFChars(env, string, str);
char* s;
return (*env)->NewStringUTF(env, s);

Frequent FULL GC log.

434711.391: [Full GC 463295K->463264K(463296K), 1.4745520 secs]
434712.868: [Full GC 463296K->463264K(463296K), 1.4686460 secs]
434724.339: [Full GC 463295K->463264K(463296K), 1.5353370 secs]
434735.877: [Full GC 463295K->463264K(463296K), 1.5300430 secs]
434737.409: [Full GC 463296K->463264K(463296K), 1.4186100 secs]
434748.830: [Full GC 463295K->463265K(463296K), 1.6480810 secs]
434760.481: [Full GC 463295K->463264K(463296K), 1.4662190 secs]
434771.949: [Full GC 463295K->463264K(463296K), 1.4691700 secs]
434773.420: [Full GC 463295K->463265K(463296K), 1.4697440 secs]
434784.893: [Full GC 463295K->463264K(463296K), 1.6079780 secs]
434796.502: [Full GC 463295K->463264K(463296K), 1.5225740 secs]
434798.027: [Full GC 463295K->463265K(463296K), 1.3949160 secs]

Thanks for any help and suggestions!

Wild Goat
  • 3,509
  • 12
  • 46
  • 87
  • Maybe this will help: [Do I need to clean up the char* passed to NewStringUTF?](http://stackoverflow.com/questions/827549/do-i-need-to-clean-up-the-char-passed-to-newstringutf) – Anto Jurković Feb 26 '15 at 18:01
  • Have you checked Java GC output? Java VM likes to constantly increase footprint unless limits are reached... – Valeri Atamaniouk Feb 26 '15 at 18:03
  • I see nothing wrong with your code. As Valeri mentioned, the JVM itself may be allocating memory inside NewStringUTF() or in other places and not freeing it (at least not in a timely fashion), because that's how the GC does things. – Wheezil Mar 01 '15 at 21:52
  • I've added GC log. @Wheezil, what do you mean by `how the GC does things`? Do you see any way I can fix an issue? I found that this issue might be fixed with `DeleteLocalRef()`, does it make sense for you? – Wild Goat Mar 02 '15 at 15:40
  • I mean, the GC is free to finalize and reclaim memory at any time after it has been released, or never, as it sees fit. And valgrind operates at a lower level than the JVM, so even if the JVM frees some memory "in the java model" that doesn't mean it releases the containing raw block(s) back to the OS -- it usually keeps them around and recycles them for later use. – Wheezil Sep 30 '15 at 12:24

0 Answers0