4

Here's a simplified version of the code I'm using

Java:

private native void malloc(int bytes);
private native void free();

// this is called when I want to create a very large buffer in native memory
malloc(32 * 1024 * 1024);

// EDIT: after allocating, we need to initialize it before Android sees it as anythign other than a "reservation"
memset(blob, '\0', sizeof(char) * bytes);


...

// and when I'm done, I call this
free()

C:

static char* blob = NULL;

void Java_com_example_MyClass_malloc(JNIEnv * env, jobject this, jint bytes)
{

    blob = (char*) malloc(sizeof(char) * bytes);

    if (NULL == blob) {
    __android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "Failed to allocate memory\n");
    } else {
        char m[50];
        sprintf(m, "Allocated %d bytes", sizeof(char) * bytes);
        __android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, m);
    }
}

void Java_com_example_MyClass_free(JNIEnv * env, jobject this)
{
    free(blob);
    blob = NULL;
}

Now when I call malloc() from MyClass.java, I would expect to see 32M of memory allocated and that I would be able to observe this drop in available memory somewhere. I haven't seen any indication of that however, either in adb shell dumpsys meminfo or adb shell cat /proc/meminfo. I am pretty new to C, but have a bunch of Java experience. I'm looking to allocate a bunch of memory outside of Dalvik's heap (so it's not managed by Android/dalvik) for testing purposes. Hackbod has led me to believe that Android currently does not place restrictions on the amount of memory allocated in Native code, so this seems to be the correct approach. Am I doing this right?

nhaarman
  • 98,571
  • 55
  • 246
  • 278
CtrlF
  • 674
  • 3
  • 8
  • 17
  • Does any debug appear in log cat? – freddy.smith Apr 11 '13 at 18:54
  • Yes, log messages appear as expected. – CtrlF Apr 11 '13 at 19:28
  • 1
    Seems correct, see http://stackoverflow.com/questions/2298208/how-to-discover-memory-usage-of-my-application-in-android/2299813#2299813 for in-depth discussion about memory usage – j.holetzeck Apr 11 '13 at 20:27
  • Looking at the output of `top -m 20 -s vss` on the device, I can see the VSS increasing, but isn't VSS essentially a worthless 'Virtual' metric? – CtrlF Apr 11 '13 at 20:30
  • The missing peice: `memset(blob, '\0', sizeof(char) * bytes);` Edited original question. – CtrlF Apr 11 '13 at 21:31
  • Use *run-as* in the adb shell to become the userid of your app, then have a look in /proc/*pid*/maps and the like. Also, you seem to have mistakenly posted your memset in the java code rather than the native. – Chris Stratton Apr 11 '13 at 22:05
  • Has Google placed any restriction on the amount of memory allocated in Native code in Android 4.4 and above? This code works for me below 4.4 but fails on 4.4 and above. On 4.4 and above malloc return NULL after few amount of memory has been allocated – Nishant Shah Sep 09 '14 at 13:35

1 Answers1

3

You should see an increase in "private / dirty" pages after the memset(). If you have the extra developer command-line utilities installed on the device, you can run procrank or showmap <pid> to see this easily. Requires a rooted device.

Failing that, have the process copy the contents of /proc/self/maps to a file before and after the allocation. (Easiest is to write it to external storage; you'll need the WRITE_EXTERNAL_STORAGE permission in your manifest.) By comparing the map output you should either see a new 32MB region, or an existing region expanding by 32MB. This works because 32MB is above dlmalloc's internal-heap threshold, so the memory should be allocated using a call to mmap().

There is no fixed limit on the amount of memory you can allocate from native code. However, the more you allocate, the tastier you look to the kernel's low-memory process killer.

fadden
  • 51,356
  • 5
  • 116
  • 166