Rectangle 27 944

Note that memory usage on modern operating systems like Linux is an extremely complicated and difficult to understand area. In fact the chances of you actually correctly interpreting whatever numbers you get is extremely low. (Pretty much every time I look at memory usage numbers with other engineers, there is always a long discussion about what they actually mean that only results in a vague conclusion.)

Note: we now have much more extensive documentation on Managing Your App's Memory that covers much of the material here and is more up-to-date with the state of Android.

First thing is to probably read the last part of this article which has some discussion of how memory is managed on Android:

Now ActivityManager.getMemoryInfo() is our highest-level API for looking at overall memory usage. This is mostly there to help an application gauge how close the system is coming to having no more memory for background processes, thus needing to start killing needed processes like services. For pure Java applications, this should be of little use, since the Java heap limit is there in part to avoid one app from being able to stress the system to this point.

Going lower-level, you can use the Debug API to get raw kernel-level information about memory usage: android.os.Debug.MemoryInfo

ActivityManager.getProcessMemoryInfo

This returns a low-level MemoryInfo structure with all of this data:

/** The proportional set size for dalvik. */
    public int dalvikPss;
    /** The private dirty pages used by dalvik. */
    public int dalvikPrivateDirty;
    /** The shared dirty pages used by dalvik. */
    public int dalvikSharedDirty;

    /** The proportional set size for the native heap. */
    public int nativePss;
    /** The private dirty pages used by the native heap. */
    public int nativePrivateDirty;
    /** The shared dirty pages used by the native heap. */
    public int nativeSharedDirty;

    /** The proportional set size for everything else. */
    public int otherPss;
    /** The private dirty pages used by everything else. */
    public int otherPrivateDirty;
    /** The shared dirty pages used by everything else. */
    public int otherSharedDirty;

But as to what the difference is between Pss, PrivateDirty, and SharedDirty... well now the fun begins.

A lot of memory in Android (and Linux systems in general) is actually shared across multiple processes. So how much memory a processes uses is really not clear. Add on top of that paging out to disk (let alone swap which we don't use on Android) and it is even less clear.

Thus if you were to take all of the physical RAM actually mapped in to each process, and add up all of the processes, you would probably end up with a number much greater than the actual total RAM.

The Pss number is a metric the kernel computes that takes into account memory sharing -- basically each page of RAM in a process is scaled by a ratio of the number of other processes also using that page. This way you can (in theory) add up the pss across all processes to see the total RAM they are using, and compare pss between processes to get a rough idea of their relative weight.

The other interesting metric here is PrivateDirty, which is basically the amount of RAM inside the process that can not be paged to disk (it is not backed by the same data on disk), and is not shared with any other processes. Another way to look at this is the RAM that will become available to the system when that process goes away (and probably quickly subsumed into caches and other uses of it).

That is pretty much the SDK APIs for this. However there is more you can do as a developer with your device.

Using adb, there is a lot of information you can get about the memory use of a running system. A common one is the command adb shell dumpsys meminfo which will spit out a bunch of information about the memory use of each Java process, containing the above info as well as a variety of other things. You can also tack on the name or pid of a single process to see, for example adb shell dumpsys meminfo system give me the system process:

The top section is the main one, where size is the total size in address space of a particular heap, allocated is the kb of actual allocations that heap thinks it has, free is the remaining kb free the heap has for additional allocations, and pss and priv dirty are the same as discussed before specific to pages associated with each of the heaps.

If you just want to look at memory usage across all processes, you can use the command adb shell procrank. Output of this on the same system looks like:

Here the Vss and Rss columns are basically noise (these are the straight-forward address space and RAM usage of a process, where if you add up the RAM usage across processes you get an ridiculously large number).

Pss is as we've seen before, and Uss is Priv Dirty.

Interesting thing to note here: Pss and Uss are slightly (or more than slightly) different than what we saw in meminfo. Why is that? Well procrank uses a different kernel mechanism to collect its data than meminfo does, and they give slightly different results. Why is that? Honestly I haven't a clue. I believe procrank may be the more accurate one... but really, this just leave the point: "take any memory info you get with a grain of salt; often a very large grain."

Finally there is the command adb shell cat /proc/meminfo that gives a summary of the overall memory usage of the system. There is a lot of data here, only the first few numbers worth discussing (and the remaining ones understood by few people, and my questions of those few people about them often resulting in conflicting explanations):

MemTotal is the total amount of memory available to the kernel and user space (often less than the actual physical RAM of the device, since some of that RAM is needed for the radio, DMA buffers, etc).

MemFree is the amount of RAM that is not being used at all. The number you see here is very high; typically on an Android system this would be only a few MB, since we try to use available memory to keep processes running

Cached is the RAM being used for filesystem caches and other such things. Typical systems will need to have 20MB or so for this to avoid getting into bad paging states; the Android out of memory killer is tuned for a particular system to make sure that background processes are killed before the cached RAM is consumed too much by them to result in such paging.

Have a look at pixelbeat.org/scripts/ps_mem.py which uses the techniques mentioned above to show used RAM for programs

Very nice written! I wrote a post on memory management and use of different tools to inspect your heap usage here macgyverdev.blogspot.com/2011/11/ if anyone finds it useful.

What exactly are the two columns "dalvik" an "native"?

What exactly are "native" "dalvik" "other"? In my app, "other" is very huge? how can I reduce it?

I can use "adb shell dumpsys meminfo",but "adb shell procrank tell me "/system/bin/sh: procrank: not found". I haven't a clue.Wish you can help me.

java - How do I discover memory usage of my application in Android? - ...

java android memory memory-management
Rectangle 27 27

But that is about a "standard" type of memory leak, when you cannot access the memory anymore, but it is still owned by the application. You can instead keep references to unused objects, or open streams without closing them afterwards.

That depends on the definition of "memory leak". If "memory that's held on to, but no longer needed", then it's easy to do in Java. If it's "memory that's allocated but not accessible by the code at all", then it gets slightly harder.

@Joachim Sauer - I meant the second type. The first is fairly easy to make :)

"With pure java, it is almost impossible." Well, my experience is another especially when it comes to implementing caches by people that are not aware of the pitfalls here.

@Rogach: there are basically +400 upvotes on various answers by people with +10 000 rep showing that in both the cases Joachim Sauer commented it's very possible. So your "almost impossible" makes no sense.

Creating a memory leak with Java - Stack Overflow

java memory memory-leaks
Rectangle 27 27

But that is about a "standard" type of memory leak, when you cannot access the memory anymore, but it is still owned by the application. You can instead keep references to unused objects, or open streams without closing them afterwards.

That depends on the definition of "memory leak". If "memory that's held on to, but no longer needed", then it's easy to do in Java. If it's "memory that's allocated but not accessible by the code at all", then it gets slightly harder.

@Joachim Sauer - I meant the second type. The first is fairly easy to make :)

"With pure java, it is almost impossible." Well, my experience is another especially when it comes to implementing caches by people that are not aware of the pitfalls here.

@Rogach: there are basically +400 upvotes on various answers by people with +10 000 rep showing that in both the cases Joachim Sauer commented it's very possible. So your "almost impossible" makes no sense.

Creating a memory leak with Java - Stack Overflow

java memory memory-leaks
Rectangle 27 25

But that is about a "standard" type of memory leak, when you cannot access the memory anymore, but it is still owned by the application. You can instead keep references to unused objects, or open streams without closing them afterwards.

That depends on the definition of "memory leak". If "memory that's held on to, but no longer needed", then it's easy to do in Java. If it's "memory that's allocated but not accessible by the code at all", then it gets slightly harder.

@Joachim Sauer - I meant the second type. The first is fairly easy to make :)

"With pure java, it is almost impossible." Well, my experience is another especially when it comes to implementing caches by people that are not aware of the pitfalls here.

@Rogach: there are basically +400 upvotes on various answers by people with +10 000 rep showing that in both the cases Joachim Sauer commented it's very possible. So your "almost impossible" makes no sense.

Creating a memory leak with Java - Stack Overflow

java memory memory-leaks
Rectangle 27 25

But that is about a "standard" type of memory leak, when you cannot access the memory anymore, but it is still owned by the application. You can instead keep references to unused objects, or open streams without closing them afterwards.

That depends on the definition of "memory leak". If "memory that's held on to, but no longer needed", then it's easy to do in Java. If it's "memory that's allocated but not accessible by the code at all", then it gets slightly harder.

@Joachim Sauer - I meant the second type. The first is fairly easy to make :)

"With pure java, it is almost impossible." Well, my experience is another especially when it comes to implementing caches by people that are not aware of the pitfalls here.

@Rogach: there are basically +400 upvotes on various answers by people with +10 000 rep showing that in both the cases Joachim Sauer commented it's very possible. So your "almost impossible" makes no sense.

Creating a memory leak with Java - Stack Overflow

java memory memory-leaks
Rectangle 27 25

But that is about a "standard" type of memory leak, when you cannot access the memory anymore, but it is still owned by the application. You can instead keep references to unused objects, or open streams without closing them afterwards.

That depends on the definition of "memory leak". If "memory that's held on to, but no longer needed", then it's easy to do in Java. If it's "memory that's allocated but not accessible by the code at all", then it gets slightly harder.

@Joachim Sauer - I meant the second type. The first is fairly easy to make :)

"With pure java, it is almost impossible." Well, my experience is another especially when it comes to implementing caches by people that are not aware of the pitfalls here.

@Rogach: there are basically +400 upvotes on various answers by people with +10 000 rep showing that in both the cases Joachim Sauer commented it's very possible. So your "almost impossible" makes no sense.

Creating a memory leak with Java - Stack Overflow

java memory memory-leaks
Rectangle 27 25

But that is about a "standard" type of memory leak, when you cannot access the memory anymore, but it is still owned by the application. You can instead keep references to unused objects, or open streams without closing them afterwards.

That depends on the definition of "memory leak". If "memory that's held on to, but no longer needed", then it's easy to do in Java. If it's "memory that's allocated but not accessible by the code at all", then it gets slightly harder.

@Joachim Sauer - I meant the second type. The first is fairly easy to make :)

"With pure java, it is almost impossible." Well, my experience is another especially when it comes to implementing caches by people that are not aware of the pitfalls here.

@Rogach: there are basically +400 upvotes on various answers by people with +10 000 rep showing that in both the cases Joachim Sauer commented it's very possible. So your "almost impossible" makes no sense.

Creating a memory leak with Java - Stack Overflow

java memory memory-leaks
Rectangle 27 14

JniBitmapHolder.java - the "bridge" between JNI and JAVA :

the sample code shows how to store 2 different bitmaps (small ones, but it's just a demo), recycle the original java ones, and later restore them to java instances and use them.

as you might guess, the layout has 2 imageViews. i didn't include it in the code since it's quite obvious.

package com.example.jnibitmapstoragetest;
...
public class JniBitmapHolder
  {
  ByteBuffer _handler =null;
  static
    {
    System.loadLibrary("JniBitmapStorageTest");
    }

  private native ByteBuffer jniStoreBitmapData(Bitmap bitmap);

  private native Bitmap jniGetBitmapFromStoredBitmapData(ByteBuffer handler);

  private native void jniFreeBitmapData(ByteBuffer handler);

  public JniBitmapHolder()
    {}

  public JniBitmapHolder(final Bitmap bitmap)
    {
    storeBitmap(bitmap);
    }

  public void storeBitmap(final Bitmap bitmap)
    {
    if(_handler!=null)
      freeBitmap();
    _handler=jniStoreBitmapData(bitmap);
    }

  public Bitmap getBitmap()
    {
    if(_handler==null)
      return null;
    return jniGetBitmapFromStoredBitmapData(_handler);
    }

  public Bitmap getBitmapAndFree()
    {
    final Bitmap bitmap=getBitmap();
    freeBitmap();
    return bitmap;
    }

  public void freeBitmap()
    {
    if(_handler==null)
      return;
    jniFreeBitmapData(_handler);
    _handler=null;
    }

  @Override
  protected void finalize() throws Throwable
    {
    super.finalize();
    if(_handler==null)
      return;
    Log.w("DEBUG","JNI bitmap wasn't freed nicely.please rememeber to free the bitmap as soon as you can");
    freeBitmap();
    }
  }
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := JniBitmapStorageTest
LOCAL_SRC_FILES := JniBitmapStorageTest.cpp
LOCAL_LDLIBS := -llog
LOCAL_LDFLAGS += -ljnigraphics

include $(BUILD_SHARED_LIBRARY)
APP_OPTIM := debug
LOCAL_CFLAGS := -g
#include <jni.h>
#include <jni.h>
#include <android/log.h>
#include <stdio.h>
#include <android/bitmap.h>
#include <cstring>
#include <unistd.h>

#define  LOG_TAG    "DEBUG"
#define  LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)
#define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)

extern "C"
  {
  JNIEXPORT jobject JNICALL Java_com_example_jnibitmapstoragetest_JniBitmapHolder_jniStoreBitmapData(JNIEnv * env, jobject obj, jobject bitmap);
  JNIEXPORT jobject JNICALL Java_com_example_jnibitmapstoragetest_JniBitmapHolder_jniGetBitmapFromStoredBitmapData(JNIEnv * env, jobject obj, jobject handle);
  JNIEXPORT void JNICALL Java_com_example_jnibitmapstoragetest_JniBitmapHolder_jniFreeBitmapData(JNIEnv * env, jobject obj, jobject handle);
  }

class JniBitmap
  {
  public:
    uint32_t* _storedBitmapPixels;
    AndroidBitmapInfo _bitmapInfo;
    JniBitmap()
      {
      _storedBitmapPixels = NULL;
      }
  };

JNIEXPORT void JNICALL Java_com_example_jnibitmapstoragetest_JniBitmapHolder_jniFreeBitmapData(JNIEnv * env, jobject obj, jobject handle)
  {
  JniBitmap* jniBitmap = (JniBitmap*) env->GetDirectBufferAddress(handle);
  if (jniBitmap->_storedBitmapPixels == NULL)
    return;
  delete[] jniBitmap->_storedBitmapPixels;
  jniBitmap->_storedBitmapPixels = NULL;
  delete jniBitmap;
  }

JNIEXPORT jobject JNICALL Java_com_example_jnibitmapstoragetest_JniBitmapHolder_jniGetBitmapFromStoredBitmapData(JNIEnv * env, jobject obj, jobject handle)
  {
  JniBitmap* jniBitmap = (JniBitmap*) env->GetDirectBufferAddress(handle);
  if (jniBitmap->_storedBitmapPixels == NULL)
    {
    LOGD("no bitmap data was stored. returning null...");
    return NULL;
    }
  //
  //creating a new bitmap to put the pixels into it - using Bitmap Bitmap.createBitmap (int width, int height, Bitmap.Config config) :
  //
  //LOGD("creating new bitmap...");
  jclass bitmapCls = env->FindClass("android/graphics/Bitmap");
  jmethodID createBitmapFunction = env->GetStaticMethodID(bitmapCls, "createBitmap", "(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;");
  jstring configName = env->NewStringUTF("ARGB_8888");
  jclass bitmapConfigClass = env->FindClass("android/graphics/Bitmap$Config");
  jmethodID valueOfBitmapConfigFunction = env->GetStaticMethodID(bitmapConfigClass, "valueOf", "(Ljava/lang/String;)Landroid/graphics/Bitmap$Config;");
  jobject bitmapConfig = env->CallStaticObjectMethod(bitmapConfigClass, valueOfBitmapConfigFunction, configName);
  jobject newBitmap = env->CallStaticObjectMethod(bitmapCls, createBitmapFunction, jniBitmap->_bitmapInfo.height, jniBitmap->_bitmapInfo.width, bitmapConfig);
  //
  // putting the pixels into the new bitmap:
  //
  int ret;
  void* bitmapPixels;
  if ((ret = AndroidBitmap_lockPixels(env, newBitmap, &bitmapPixels)) < 0)
    {
    LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
    return NULL;
    }
  uint32_t* newBitmapPixels = (uint32_t*) bitmapPixels;
  int pixelsCount = jniBitmap->_bitmapInfo.height * jniBitmap->_bitmapInfo.width;
  memcpy(newBitmapPixels, jniBitmap->_storedBitmapPixels, sizeof(uint32_t) * pixelsCount);
  AndroidBitmap_unlockPixels(env, newBitmap);
  //LOGD("returning the new bitmap");
  return newBitmap;
  }

JNIEXPORT jobject JNICALL Java_com_example_jnibitmapstoragetest_JniBitmapHolder_jniStoreBitmapData(JNIEnv * env, jobject obj, jobject bitmap)
  {
  AndroidBitmapInfo bitmapInfo;
  uint32_t* storedBitmapPixels = NULL;
  //LOGD("reading bitmap info...");
  int ret;
  if ((ret = AndroidBitmap_getInfo(env, bitmap, &bitmapInfo)) < 0)
    {
    LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
    return NULL;
    }
  LOGD("width:%d height:%d stride:%d", bitmapInfo.width, bitmapInfo.height, bitmapInfo.stride);
  if (bitmapInfo.format != ANDROID_BITMAP_FORMAT_RGBA_8888)
    {
    LOGE("Bitmap format is not RGBA_8888!");
    return NULL;
    }
  //
  //read pixels of bitmap into native memory :
  //
  //LOGD("reading bitmap pixels...");
  void* bitmapPixels;
  if ((ret = AndroidBitmap_lockPixels(env, bitmap, &bitmapPixels)) < 0)
    {
    LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
    return NULL;
    }
  uint32_t* src = (uint32_t*) bitmapPixels;
  storedBitmapPixels = new uint32_t[bitmapInfo.height * bitmapInfo.width];
  int pixelsCount = bitmapInfo.height * bitmapInfo.width;
  memcpy(storedBitmapPixels, src, sizeof(uint32_t) * pixelsCount);
  AndroidBitmap_unlockPixels(env, bitmap);
  JniBitmap *jniBitmap = new JniBitmap();
  jniBitmap->_bitmapInfo = bitmapInfo;
  jniBitmap->_storedBitmapPixels = storedBitmapPixels;
  return env->NewDirectByteBuffer(jniBitmap, 0);
  }

Yes, github project working fine. so i want to include it with my project and i tried both ways converted sample project in library and in android tag i included it. it is not showing any error on compile time but on run time ExceptionInInitializerError. I think problem is here System.loadLibrary("JniBitmapOperations"); or may b its packeg name problem. I never used ndk.how to implement it?

You will need to do some research on this. please continue the comments where you started it instead of multiple places. however, you are correct that the package is important, as the code in the C/C++ side assumes about their paths.

Thanks for reply. What i have to change if i make ur project as library project and include it in my app. like pkg name or path?

is it your first time of importing an android library, or do you have a specific problem with this one in particular? if there is a problem with this one, you can just copy its files to your project, change the packages paths inside all files (especially the C/C++ files) , and it should work fine.

depends on what you do with it (in which package you put it).

android - How to cache bitmaps into native memory - Stack Overflow

android caching bitmap jni native
Rectangle 27 20

  • Java compiles to bytecode, and the bytecode compiles to native code by the JIT.

The difference are really the extra compile step, and in theory java should do a better work then your C compiler, and here's why:

  • Java can insert statistics calculations into the generated native code, and then after a while regenerate it to optimize it against the current runtime paths in your code!

That last point sounds awesome, java do however come with some tradeoffs:

GC copies alive objects and throws all dead one, since GC does not need to do anything for the dead one only for the live ones, GC in theory is faster then the normal malloc/free loop for objects.

However, one thing is forgotten by most Java advocates and that is that nothing says that you will have to malloc/free every object instance when coding C. You can reuse memory, you can malloc up memory blocks and free memory blocks containing thousands of temporarily objects on one go.

With big heaps on Java, GC time increases, adding stall time. In some software it is totally OK with stall times during GC cleanup cycle, in others it causes fatal errors. Try keeping your software to respond under a defined number of milliseconds when a GC happens, and you will see what I'm talking about.

In some extreme cases, the JIT may also choose not to JIT the code at all. This happens when a JITed method would be to big, 8K if I remember correct. A non JITed method has a runtime penalty in the range of 20000% (200 times slower that is, at least at our customer it was). JIT is also turned of when the JVMs CodeCache starts to get full (if keep loading new classes into the JVM over and over again this can happen, also happen at customer site). At one point JIT statistics also reduced concurrency on one 128 core machine to basically single core performance.

In Java the JIT has a specific amount of time to compile the bytecode to native code, it is not OK to spend all CPU resources for the JIT, since it runs in parallel with the code doing the actually work of your program. In C the compiler can run as long as it needs to spit out what it thinks is the most optimized code it can. It has no impact on execution time, where in Java it has.

  • Java gives you more, but it's not always up to you how it performs.

If you only keep to simple math over a preallocate buffer, both Java and C compilers should spit out about the same code.

So as i under stand,if i will calculate this expression : arr[i]=arr1[i]/arr2[2] it will take the same time in the 2 cases?

this answer is nice but it's not related to android. something should be said about if android lets you go around java with c++. it does. stackoverflow.com/questions/8922608/

to add to this. java is not good for parallel programming because oop is not good for that. also java doesn't have meta-programming that is as good as c++'s

android - NDK vs JAVA performance - Stack Overflow

java android c android-ndk
Rectangle 27 17

I think the problem is this: On pre-Honeycomb versions of Android, the actual raw bitmap data is not stored in VM memory but in native memory instead. This native memory is freed when the corresponding java Bitmap object is GC'd.

However, when you run out of native memory, the dalvik GC isn't triggered, so it is possible that your app uses very little of the java memory, so the dalvik GC is never invoked, yet it uses tons of native memory for bitmaps which eventually causes an OOM error.

At least that's my guess. Thankfully in Honeycomb and later, all bitmap data is stored in the VM so you shouldn't have to use recycle() at all. But for the millions of 2.3 users (fragmentation shakes fist), you should use recycle() wherever possible (a massive hassle). Or alternatively you may be able to invoke the GC instead.

Android: Bitmap recycle() how does it work? - Stack Overflow

android bitmap
Rectangle 27 9

The amount of memory allocated for the Java process is pretty much on-par with what I would expect. I've had similar problems running Java on embedded/memory limited systems. Running any application with arbitrary VM limits or on systems that don't have adequate amounts of swap tend to break. It seems to be the nature of many modern apps that aren't design for use on resource-limited systems.

You have a few more options you can try and limit your JVM's memory footprint. This might reduce the virtual memory footprint:

-XX:ReservedCodeCacheSize=32m Reserved code cache size (in bytes) - maximum code cache size. [Solaris 64-bit, amd64, and -server x86: 48m; in 1.5.0_06 and earlier, Solaris 64-bit and and64: 1024m.]

-XX:MaxPermSize=64m Size of the Permanent Generation. [5.0 and newer: 64 bit VMs are scaled 30% larger; 1.4 amd64: 96m; 1.3.1 -client: 32m.]

Also, you also should set your -Xmx (max heap size) to a value as close as possible to the actual peak memory usage of your application. I believe the default behavior of the JVM is still to double the heap size each time it expands it up to the max. If you start with 32M heap and your app peaked to 65M, then the heap would end up growing 32M -> 64M -> 128M.

You might also try this to make the VM less aggressive about growing the heap:

-XX:MinHeapFreeRatio=40 Minimum percentage of heap free after GC to avoid expansion.

Also, from what I recall from experimenting with this a few years ago, the number of native libraries loaded had a huge impact on the minimum footprint. Loading java.net.Socket added more than 15M if I recall correctly (and I probably don't).

Virtual Memory Usage from Java under Linux, too much memory used - Sta...

java linux memory virtual-memory
Rectangle 27 7

The Xmx parameter does only specify the size of the heap. The Java process takes more memory since the heap is only one part of the Java process, I guess you also have other stuff that the java process contains like native libraries, the perm gen and also native memory allocations made by the application.

java - Does the JVM force garbage collection when it reaches its -Xmx ...

java memory-management garbage-collection
Rectangle 27 33

The memory that backs a Bitmap object is allocated using native code (malloc()), rather than the Java new keyword. This means that the memory is managed directly by the OS, rather than by Dalvik.

The only real difference between the native heap and Dalvik's heap is that Dalvik's heap is garbage collected, and the native one isn't.

For these purposes though, here's not much difference. When your Bitmap object gets garbage collected, it's destructor will recycle the associated memory in the native heap.

Do you know if this bug was ever fixed? I'm currently running into the same problem on the thunder bolt. I'm recycling the bitmaps but they're never clearing any space on the native heap causing oom errors.

Just for clarity, the above answer is true for android version 2.x and below. Starting with Android 3, bitmap instances are counter agains the heap. This can easily be checked: creating a bitmap in android 2.x will leave the Java heap size pretty much intouched, creating it in Adnroid 3.x will add a lot of bytes to the Java heap.

Ah! so you are saying the counting is now much more intuitive? That's great - except for all of us who wrote hacky code to sum the android heap with the native heap ...

Bitmaps in Android - Stack Overflow

android bitmap
Rectangle 27 33

The memory that backs a Bitmap object is allocated using native code (malloc()), rather than the Java new keyword. This means that the memory is managed directly by the OS, rather than by Dalvik.

The only real difference between the native heap and Dalvik's heap is that Dalvik's heap is garbage collected, and the native one isn't.

For these purposes though, here's not much difference. When your Bitmap object gets garbage collected, it's destructor will recycle the associated memory in the native heap.

Do you know if this bug was ever fixed? I'm currently running into the same problem on the thunder bolt. I'm recycling the bitmaps but they're never clearing any space on the native heap causing oom errors.

Just for clarity, the above answer is true for android version 2.x and below. Starting with Android 3, bitmap instances are counter agains the heap. This can easily be checked: creating a bitmap in android 2.x will leave the Java heap size pretty much intouched, creating it in Adnroid 3.x will add a lot of bytes to the Java heap.

Ah! so you are saying the counting is now much more intuitive? That's great - except for all of us who wrote hacky code to sum the android heap with the native heap ...

Bitmaps in Android - Stack Overflow

android bitmap
Rectangle 27 1

The current garbage collector in Java is well known for not releasing allocated memory, although the memory is not required anymore. It's quite strange however, that your RSS size increases to >3GB although your heap size is limited to 640MB. Are you using any native code in your application or are you having the native performance optimization pack for Tomcat enabled? In that case, you may of course have a native memory leak in your code or in Tomcat.

With Java 6u14, Sun introduced the new "Garbage-First" garbage collector, which is able to release memory back to the operating system if it's not required anymore. It's still categorized as experimental and not enabled by default, but if it is a feasible option for you, I would try to upgrade to the newest Java 6 release and enable the new garbage collector with the command line arguments "-XX:+UnlockExperimentalVMOptions -XX:+UseG1GC". It might solve your problem.

No JNI, but the application does rely heavily on java.nio.FileChannel to send data from disk to NIC...

And you are not using the native Tomcat functionaliy (tomcat.apache.org/tomcat-6.0-doc/apr.html)? Unless you are keeping references to a lot of open FileChannel objects (and this would cause other problems, like reaching the max number of open files allowed), FileChannel usage alone is not really an explanation of your applications behaviour.

No, I'm not. a) is it is flaky on 64-bit Linux (or was last time I checked), b) I had issues with in an a 3rd party jar, and c) I really don't have that many connections per second to worry about connector performance.

java - Why does the Sun JVM continue to consume ever more RSS memory e...

java memory jvm sun performance
Rectangle 27 2

The limit is based on NativeHeapAllocSize vs. maxMemory(). You will see below that I'm crashing allocating ~1 MiB while I'm at 22.0 MiB / 24 MiB. The limit is an UPPER BOUND on how much memory you can allocate. This is what threw me for a while. The crash happens significantly before you hit the limit. Thus, the need for a "memoryPad" value in the solution, as trying to alloc 23.999 MiB / 24 MiB will result in a crash nearly 100% of the time. So if the limit is 24 MiB, how much can you safely use?? Unknown. 20 MiB seems to work. 22 MiB seems to work. I'm nervous pushing any closer than that. The ammount varies depending on how fragmented the malloc memory space is in the native process. And of course, there is no way to measure any of this, so err on the safe side.

The code to print all that out:

public static void logMemoryStats() {
        String text = "";
        text += "\nLoadedClassCount="               + toMib(android.os.Debug.getLoadedClassCount());
        text += "\nGlobalAllocSize="                + toMib(android.os.Debug.getGlobalAllocSize());
        text += "\nGlobalFreedSize="                + toMib(android.os.Debug.getGlobalFreedSize());
        text += "\nGlobalExternalAllocSize="        + toMib(android.os.Debug.getGlobalExternalAllocSize());
        text += "\nGlobalExternalFreedSize="        + toMib(android.os.Debug.getGlobalExternalFreedSize());
        text += "\nEpicPixels="                     + toMib(EpicBitmap.getGlobalPixelCount()*4);
        text += "\nNativeHeapSize="                 + toMib(android.os.Debug.getNativeHeapSize());
        text += "\nNativeHeapFree="                 + toMib(android.os.Debug.getNativeHeapFreeSize());
        text += "\nNativeHeapAllocSize="            + toMib(android.os.Debug.getNativeHeapAllocatedSize());
        text += "\nThreadAllocSize="                + toMib(android.os.Debug.getThreadAllocSize());

        text += "\ntotalMemory()="                  + toMib(Runtime.getRuntime().totalMemory());
        text += "\nmaxMemory()="                    + toMib(Runtime.getRuntime().maxMemory());
        text += "\nfreeMemory()="                   + toMib(Runtime.getRuntime().freeMemory());

        android.app.ActivityManager.MemoryInfo mi1 = new android.app.ActivityManager.MemoryInfo();
        ActivityManager am = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
        am.getMemoryInfo(mi1);
        text += "\napp.mi.availMem="                + toMib(mi1.availMem);
        text += "\napp.mi.threshold="               + toMib(mi1.threshold);
        text += "\napp.mi.lowMemory="               + mi1.lowMemory;

        android.os.Debug.MemoryInfo mi2 = new android.os.Debug.MemoryInfo();        
        Debug.getMemoryInfo(mi2);
        text += "\ndbg.mi.dalvikPrivateDirty="      + toMib(mi2.dalvikPrivateDirty);
        text += "\ndbg.mi.dalvikPss="               + toMib(mi2.dalvikPss);
        text += "\ndbg.mi.dalvikSharedDirty="       + toMib(mi2.dalvikSharedDirty);
        text += "\ndbg.mi.nativePrivateDirty="      + toMib(mi2.nativePrivateDirty);
        text += "\ndbg.mi.nativePss="               + toMib(mi2.nativePss);
        text += "\ndbg.mi.nativeSharedDirty="       + toMib(mi2.nativeSharedDirty);
        text += "\ndbg.mi.otherPrivateDirty="       + toMib(mi2.otherPrivateDirty);
        text += "\ndbg.mi.otherPss"                 + toMib(mi2.otherPss);
        text += "\ndbg.mi.otherSharedDirty="        + toMib(mi2.otherSharedDirty);

        EpicLog.i("ArchPlatform[android].logStats() - " + text);
    }

@dpk - toMib is a helper that formats large byte counts into more friendly "12.3 MiB" ... MiB is the more pedantic form of MB that implies base-1024 SI units instead of base-1000. I probably didn't realize I used it and didn't paste it. You could remove it or make it your own favorite format at no loss to the intention of the code.

out of memory - Android Bitmap Limit - Preventing java.lang.OutOfMemor...

android out-of-memory
Rectangle 27 2

The limit is based on NativeHeapAllocSize vs. maxMemory(). You will see below that I'm crashing allocating ~1 MiB while I'm at 22.0 MiB / 24 MiB. The limit is an UPPER BOUND on how much memory you can allocate. This is what threw me for a while. The crash happens significantly before you hit the limit. Thus, the need for a "memoryPad" value in the solution, as trying to alloc 23.999 MiB / 24 MiB will result in a crash nearly 100% of the time. So if the limit is 24 MiB, how much can you safely use?? Unknown. 20 MiB seems to work. 22 MiB seems to work. I'm nervous pushing any closer than that. The ammount varies depending on how fragmented the malloc memory space is in the native process. And of course, there is no way to measure any of this, so err on the safe side.

The code to print all that out:

public static void logMemoryStats() {
        String text = "";
        text += "\nLoadedClassCount="               + toMib(android.os.Debug.getLoadedClassCount());
        text += "\nGlobalAllocSize="                + toMib(android.os.Debug.getGlobalAllocSize());
        text += "\nGlobalFreedSize="                + toMib(android.os.Debug.getGlobalFreedSize());
        text += "\nGlobalExternalAllocSize="        + toMib(android.os.Debug.getGlobalExternalAllocSize());
        text += "\nGlobalExternalFreedSize="        + toMib(android.os.Debug.getGlobalExternalFreedSize());
        text += "\nEpicPixels="                     + toMib(EpicBitmap.getGlobalPixelCount()*4);
        text += "\nNativeHeapSize="                 + toMib(android.os.Debug.getNativeHeapSize());
        text += "\nNativeHeapFree="                 + toMib(android.os.Debug.getNativeHeapFreeSize());
        text += "\nNativeHeapAllocSize="            + toMib(android.os.Debug.getNativeHeapAllocatedSize());
        text += "\nThreadAllocSize="                + toMib(android.os.Debug.getThreadAllocSize());

        text += "\ntotalMemory()="                  + toMib(Runtime.getRuntime().totalMemory());
        text += "\nmaxMemory()="                    + toMib(Runtime.getRuntime().maxMemory());
        text += "\nfreeMemory()="                   + toMib(Runtime.getRuntime().freeMemory());

        android.app.ActivityManager.MemoryInfo mi1 = new android.app.ActivityManager.MemoryInfo();
        ActivityManager am = (ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE);
        am.getMemoryInfo(mi1);
        text += "\napp.mi.availMem="                + toMib(mi1.availMem);
        text += "\napp.mi.threshold="               + toMib(mi1.threshold);
        text += "\napp.mi.lowMemory="               + mi1.lowMemory;

        android.os.Debug.MemoryInfo mi2 = new android.os.Debug.MemoryInfo();        
        Debug.getMemoryInfo(mi2);
        text += "\ndbg.mi.dalvikPrivateDirty="      + toMib(mi2.dalvikPrivateDirty);
        text += "\ndbg.mi.dalvikPss="               + toMib(mi2.dalvikPss);
        text += "\ndbg.mi.dalvikSharedDirty="       + toMib(mi2.dalvikSharedDirty);
        text += "\ndbg.mi.nativePrivateDirty="      + toMib(mi2.nativePrivateDirty);
        text += "\ndbg.mi.nativePss="               + toMib(mi2.nativePss);
        text += "\ndbg.mi.nativeSharedDirty="       + toMib(mi2.nativeSharedDirty);
        text += "\ndbg.mi.otherPrivateDirty="       + toMib(mi2.otherPrivateDirty);
        text += "\ndbg.mi.otherPss"                 + toMib(mi2.otherPss);
        text += "\ndbg.mi.otherSharedDirty="        + toMib(mi2.otherSharedDirty);

        EpicLog.i("ArchPlatform[android].logStats() - " + text);
    }

@dpk - toMib is a helper that formats large byte counts into more friendly "12.3 MiB" ... MiB is the more pedantic form of MB that implies base-1024 SI units instead of base-1000. I probably didn't realize I used it and didn't paste it. You could remove it or make it your own favorite format at no loss to the intention of the code.

out of memory - Android Bitmap Limit - Preventing java.lang.OutOfMemor...

android out-of-memory
Rectangle 27 4

I wasn't able to determine why memory allocation and collection is different among the different platforms, but I was able to mitigate the problem and prevent my application from crashing on any platform by scaling the images down to fit available memory.

This first function determines where the Bitmap memory is being stored (native or Java), and then calculates the remaining available memory (in KB).

private long calcAvailableMemory()
{
    long value = Runtime.getRuntime().maxMemory();
    String type = "";
    if (android.os.Build.VERSION.SDK_INT >= 11)
    {
        value = value / 1024) - (Runtime.getRuntime().totalMemory() / 1024);
        type = "JAVA";
    }
    else
    {
        value = value / 1024) - (Debug.getNativeHeapAllocatedSize() / 1024);
        type = "NATIVE";
    }
    Log.i(TAG, "calcAvailableMemory, size = " + value + ", type = " + type);
    return value;
}

This second function creates an ImageView to attach to the Layout. The Show object contains different variables I need to initialize the ImageView such as dimensions and filepath etc. The long maxImageMemory is derived from the first function, and is then divided by the number of views I'm attaching to the layout giving the me maximum amount of memory to allocate each Bitmap.

private ImageView newImage(Show show, long maxImageMemory)
{
    ImageView iv = new ImageView(this);
    String filePath = comin.generateFilePath(show);
    Bitmap bmp = scaleBitmap(filePath, maxImageMemory);
    Log.i(TAG, "newImage, id:" + show.id + ", file:" + filePath + ", x:" + bmp.getWidth() + ", y:" + bmp.getHeight());
    iv.setImageBitmap(bmp);
    iv.setScaleType(ImageView.ScaleType.FIT_XY);
    iv.setId(show.id);

    //set visibility
    if (show.visible)
        iv.setVisibility(View.VISIBLE);
    else
        iv.setVisibility(View.INVISIBLE);

    //set dimensions
    int width = (app.getWidth() * show.dimX) / 100;
    int height = (app.getHeight() * show.dimY) / 100;
    RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams(width, height);
    iv.setLayoutParams(rlp);

    return iv;
}

This third function scales the Bitmap that will be loaded into the ImageView being created in function 2. The while loop is the important part, that is where I increase the sample size until the needed memory for the bitmap is less than the maximum memory available.

private Bitmap scaleBitmap(String path, long maxImageMemory)
{
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inJustDecodeBounds = true;
    BitmapFactory.decodeFile(path, options);

    int sample = 1;
    //Scale image to screen resolution
    if (options.outHeight > app.getHeight() || options.outWidth > app.getWidth())
    {
        int heightRatio = Math.round((float) options.outHeight / (float) app.getHeight());
        int widthRatio = Math.round((float) options.outWidth / (float) app.getWidth());
        sample = heightRatio < widthRatio ? heightRatio : widthRatio;
    }

    //Scale image to stay within memory limitations
    while (calcBitmapSize(options.outWidth, options.outHeight, sample) > maxImageMemory)
    {
        sample++;
    }

    options.inSampleSize = sample;
    options.inPurgeable = true;
    options.inInputShareable = true;
    options.inJustDecodeBounds = false;

    Log.i(TAG, "scaleBitmap, scaleSample = " + sample);
    return BitmapFactory.decodeFile(path, options);
}

This fourth function calculates the amount of memory required by the Bitmap depending on the original resolution, as well as the proposed sample size.

private long calcBitmapSize(int width, int height, int sample)
{
    long value = ((width/sample) * (height/sample) * 4) / 1024;
    Log.i(TAG, "calcBitmapSize, size = " + value);
    return value;
}

Lastly, I developed this function to assist in troubleshooting all of these memory problems. It logs memory utilization depending on which version of Android you are running.

private void logMemory(String callingFunction)
{
    long max = Runtime.getRuntime().maxMemory() / 1024;

    if (debugJavaMemory)
    {
        long used = Runtime.getRuntime().totalMemory() / 1024;
        long available = max - used;
        long change = available - availableJavaMemoryOld;
        if (availableJavaMemoryOld != 0)
            Log.i(TAG_MEMORY, "jMEM M:" + max + ", U:" + used + ", A:" + available + ", C:" + change + ", " + callingFunction);
        availableJavaMemoryOld = available;
    }
    else if (debugNativeMemory)
    {
        long used = Debug.getNativeHeapAllocatedSize() / 1024;
        long available = max - used;
        long change = available - availableNativeMemoryOld;
        if (availableNativeMemoryOld != 0)
            Log.i(TAG_MEMORY, "nMEM M:" + max + ", U:" + used + ", A:" + available + ", C:" + change + ", " + callingFunction);
        availableNativeMemoryOld = available;
    }
}

Android Bitmap Memory Issue - Error: Out of memory on a 8294416-byte a...

android bitmap imageview heap out-of-memory
Rectangle 27 2

R1. The apk is just a package. When you start your application, low level, the linux machine on which Android is based will fork a process called Zygote. Then the copy of the Zygote (that already has either an instance of the Dalvik Machine mapped in its address space, or the ART libraries and Ahead Of Time compiled application code), will load all application specific java classes, and all core dependencies (native libraries), plus all application specific native code.

So it does create a new process only when you start the application.And hypothetically, you could create any number of processes for the same apk, which is just a container.

R2. If in the AndroidManifest you have a service declared as "exported", it will run in a separate process. Your application will then communicate with this process using an IPC mechanism called Binder, which is a specific implementation of shared memory at kernel level. AIDL is a meta-language interpreted at build time and used to auto-generate Java stubs that will work deep down with native binder code.

does it mean, each apk whether it is just service not activity or activity. it is separate process created internally.

I don't understand this question. You can package in an apk either a service or an application. And the service could also come with BroadcastReceivers and ContentProviders. And the application can come with multiple Activities, and also with BroadcastReceivers and ContentProviders. Al these are Android framework components, while a process is a running task. Activities are components that are displayed on screen, and usually a service has no need for such.

Whether apk contains any Activity or any Service which may be with BroadcastReceivers and ContentProviders. Once apk launch it is process right.

Android application process - Stack Overflow

android android-framework
Rectangle 27 1

On top of what some others have said, from my understanding .NET and Java are better at memory allocation. E.g. they can compact memory as it gets fragmented while C++ cannot (natively, but it can if you're using a clever garbage collector).

Or if you're using a better C++ allocator and/or pool of objects. This is far from magic, from a C++ view point, and it can boils down to have "heap allocation" become as fast a stack allocation.

If you'd always allocate everything on the heap, then .NET and Java may even perform better than C/C++. But you just will not do this in C/C++.

C++ performance vs. Java/C# - Stack Overflow

c# java c++ performance bytecode