0

I wrote an android app where I implemented a solver. The solver allocates a lot of memory. For easy problems it works without problems. But when the problem becomes more complex I get the error "Out of memory on a 2164-byte allocation" and the app crashes.

I tried to use

try {
        solver();
}
catch (Exception e) {
}

But this does not prevent the app from crashing.

I also tried "android:largeHeap="true" in the AndroidManifest.xml.

Is there a way to get more memory or to stop the solver before the memory is full?

04-18 11:39:10.953: D/dalvikvm(979): GC_FOR_ALLOC freed 25K, 5% free 31446K/32768K, paused 363ms, total 363ms
04-18 11:39:10.953: I/dalvikvm-heap(979): Forcing collection of SoftReferences for 93404-byte allocation
04-18 11:39:11.283: I/dalvikvm-heap(979): Clamp target GC heap from 32.832MB to 32.000MB
04-18 11:39:11.293: D/dalvikvm(979): GC_BEFORE_OOM freed <1K, 5% free 31445K/32768K, paused 331ms, total 332ms
04-18 11:39:11.293: E/dalvikvm-heap(979): Out of memory on a 93404-byte allocation.
04-18 11:39:11.293: I/dalvikvm(979): "AdWorker #1" prio=5 tid=11 RUNNABLE
04-18 11:39:11.293: I/dalvikvm(979):   | group="main" sCount=0 dsCount=0 obj=0xb48db908 self=0xb7ecf560
04-18 11:39:11.293: I/dalvikvm(979):   | sysTid=1015 nice=10 sched=0/0 cgrp=apps/bg_non_interactive handle=-1209206344
04-18 11:39:11.303: I/dalvikvm(979):   | state=R schedstat=( 2590000000 85040000000 791 ) utm=236 stm=23 core=0
04-18 11:39:11.303: I/dalvikvm(979):   at java.lang.AbstractStringBuilder.enlargeBuffer(AbstractStringBuilder.java:~94)
04-18 11:39:11.303: I/dalvikvm(979):   at java.lang.AbstractStringBuilder.append0(AbstractStringBuilder.java:162)
04-18 11:39:11.303: I/dalvikvm(979):   at java.lang.StringBuilder.append(StringBuilder.java:311)
04-18 11:39:11.313: I/dalvikvm(979):   at com.google.android.gms.internal.eo.a((null):-1)
04-18 11:39:11.313: I/dalvikvm(979):   at com.google.android.gms.internal.dx.a((null):-1)
04-18 11:39:11.313: I/dalvikvm(979):   at com.google.android.gms.internal.dx.a((null):-1)
04-18 11:39:11.313: I/dalvikvm(979):   at com.google.android.gms.internal.dx.b((null):-1)
04-18 11:39:11.313: I/dalvikvm(979):   at com.google.android.gms.internal.dq.a((null):-1)
04-18 11:39:11.313: I/dalvikvm(979):   at com.google.android.gms.internal.dq.bh((null):-1)
04-18 11:39:11.313: I/dalvikvm(979):   at com.google.android.gms.internal.em$1.run((null):-1)
04-18 11:39:11.313: I/dalvikvm(979):   at com.google.android.gms.internal.en$1.run((null):-1)
04-18 11:39:11.313: I/dalvikvm(979):   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
04-18 11:39:11.313: I/dalvikvm(979):   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
04-18 11:39:11.313: I/dalvikvm(979):   at java.lang.Thread.run(Thread.java:841)
04-18 11:39:11.333: I/Choreographer(979): Skipped 83 frames!  The application may be doing too much work on its main thread.
04-18 11:39:11.393: W/dalvikvm(979): threadid=11: thread exiting with uncaught exception (group=0xb3a7eba8)
04-18 11:39:11.873: I/dalvikvm-heap(979): Clamp target GC heap from 32.746MB to 32.000MB
04-18 11:39:11.883: D/dalvikvm(979): GC_FOR_ALLOC freed 132K, 5% free 31357K/32768K, paused 426ms, total 426ms
04-18 11:39:11.903: I/Choreographer(979): Skipped 44 frames!  The application may be doing too much work on its main thread.
04-18 11:39:12.613: I/dalvikvm-heap(979): Clamp target GC heap from 32.793MB to 32.000MB
04-18 11:39:12.633: D/dalvikvm(979): GC_FOR_ALLOC freed 163K, 5% free 31405K/32768K, paused 488ms, total 489ms
04-18 11:39:13.013: I/dalvikvm-heap(979): Clamp target GC heap from 32.796MB to 32.000MB
04-18 11:39:13.013: D/dalvikvm(979): GC_FOR_ALLOC freed 12K, 5% free 31409K/32768K, paused 374ms, total 374ms
04-18 11:39:13.013: I/dalvikvm-heap(979): Forcing collection of SoftReferences for 2162-byte allocation
04-18 11:39:13.373: I/dalvikvm-heap(979): Clamp target GC heap from 32.796MB to 32.000MB
04-18 11:39:13.373: D/dalvikvm(979): GC_BEFORE_OOM freed <1K, 5% free 31409K/32768K, paused 354ms, total 355ms
04-18 11:39:13.373: E/dalvikvm-heap(979): Out of memory on a 2162-byte allocation.
04-18 11:39:13.373: I/dalvikvm(979): "AdWorker #1" prio=5 tid=11 RUNNABLE
04-18 11:39:13.373: I/dalvikvm(979):   | group="main" sCount=0 dsCount=0 obj=0xb48db908 self=0xb7ecf560
04-18 11:39:13.373: I/dalvikvm(979):   | sysTid=1015 nice=10 sched=0/0 cgrp=apps/bg_non_interactive handle=-1209206344
04-18 11:39:13.383: I/dalvikvm(979):   | state=R schedstat=( 3560000000 85730000000 847 ) utm=331 stm=25 core=0
04-18 11:39:13.383: I/dalvikvm(979):   at java.lang.AbstractStringBuilder.enlargeBuffer(AbstractStringBuilder.java:~94)
04-18 11:39:13.383: I/dalvikvm(979):   at java.lang.AbstractStringBuilder.append0(AbstractStringBuilder.java:124)
04-18 11:39:13.383: I/dalvikvm(979):   at java.lang.StringBuffer.append(StringBuffer.java:278)
04-18 11:39:13.383: I/dalvikvm(979):   at java.io.StringWriter.write(StringWriter.java:123)
04-18 11:39:13.383: I/dalvikvm(979):   at com.android.internal.util.FastPrintWriter.flushLocked(FastPrintWriter.java:358)
04-18 11:39:13.383: I/dalvikvm(979):   at com.android.internal.util.FastPrintWriter.flush(FastPrintWriter.java:387)
04-18 11:39:13.383: I/dalvikvm(979):   at android.util.Log.getStackTraceString(Log.java:335)
04-18 11:39:13.383: I/dalvikvm(979):   at android.util.Slog.e(Slog.java:77)
04-18 11:39:13.383: I/dalvikvm(979):   at com.android.internal.os.RuntimeInit$UncaughtHandler.uncaughtException(RuntimeInit.java:80)
04-18 11:39:13.383: I/dalvikvm(979):   at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:693)
04-18 11:39:13.393: I/dalvikvm(979):   at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:690)
04-18 11:39:13.713: I/dalvikvm-heap(979): Clamp target GC heap from 32.799MB to 32.000MB
04-18 11:39:13.723: D/dalvikvm(979): GC_FOR_ALLOC freed 7K, 5% free 31412K/32768K, paused 327ms, total 327ms
04-18 11:39:13.723: I/dalvikvm-heap(979): Forcing collection of SoftReferences for 2164-byte allocation
04-18 11:39:14.063: I/dalvikvm-heap(979): Clamp target GC heap from 32.799MB to 32.000MB
04-18 11:39:14.063: D/dalvikvm(979): GC_BEFORE_OOM freed 0K, 5% free 31412K/32768K, paused 344ms, total 345ms
04-18 11:39:14.073: E/dalvikvm-heap(979): Out of memory on a 2164-byte allocation.
04-18 11:39:14.073: I/dalvikvm(979): "AdWorker #1" prio=5 tid=11 RUNNABLE
04-18 11:39:14.073: I/dalvikvm(979):   | group="main" sCount=0 dsCount=0 obj=0xb48db908 self=0xb7ecf560
04-18 11:39:14.073: I/dalvikvm(979):   | sysTid=1015 nice=10 sched=0/0 cgrp=apps/bg_non_interactive handle=-1209206344
04-18 11:39:14.073: I/dalvikvm(979):   | state=R schedstat=( 4210000000 85770000000 885 ) utm=395 stm=26 core=0
04-18 11:39:14.073: I/dalvikvm(979):   at java.lang.AbstractStringBuilder.enlargeBuffer(AbstractStringBuilder.java:~94)
04-18 11:39:14.073: I/dalvikvm(979):   at java.lang.AbstractStringBuilder.append0(AbstractStringBuilder.java:124)
04-18 11:39:14.073: I/dalvikvm(979):   at java.lang.StringBuffer.append(StringBuffer.java:278)
04-18 11:39:14.073: I/dalvikvm(979):   at java.io.StringWriter.write(StringWriter.java:123)
04-18 11:39:14.073: I/dalvikvm(979):   at com.android.internal.util.FastPrintWriter.flushLocked(FastPrintWriter.java:358)
04-18 11:39:14.073: I/dalvikvm(979):   at com.android.internal.util.FastPrintWriter.flush(FastPrintWriter.java:387)
04-18 11:39:14.073: I/dalvikvm(979):   at android.util.Log.getStackTraceString(Log.java:335)
04-18 11:39:14.073: I/dalvikvm(979):   at android.util.Slog.e(Slog.java:77)
04-18 11:39:14.073: I/dalvikvm(979):   at com.android.internal.os.RuntimeInit$UncaughtHandler.uncaughtException(RuntimeInit.java:88)
04-18 11:39:14.073: I/dalvikvm(979):   at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:693)
04-18 11:39:14.083: I/dalvikvm(979):   at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:690)
04-18 11:39:14.083: I/Process(979): Sending signal. PID: 979 SIG: 9
trincot
  • 317,000
  • 35
  • 244
  • 286
Vader
  • 191
  • 8
  • "But when the problem becomes more complex I get the error "Out of memory on a 2164-byte allocation" and the app crashes" -- your heap is fragmented enough that there are no more 2164-byte or larger blocks of memory available. "But this does not prevent the app from crashing" -- `OutOfMemoryError` is not an `Exception`. [It is an `Error`](http://developer.android.com/reference/java/lang/OutOfMemoryError.html). "Is there a way to get more memory" -- not from the Android SDK. "or to stop the solver before the memory is full?" -- not specifically. – CommonsWare Apr 18 '15 at 16:20
  • In general, you can use `getMemoryClass()` or `getLargeMemoryClass()` on `ActivityManager` to determine how big your heap could get. Then, use that as a guideline for how much you can allocate before you are likely to get an `OutOfMemoryError`. However, you probably should consider trying to determine why your solver takes up so much RAM. – CommonsWare Apr 18 '15 at 16:23
  • "However, you probably should consider trying to determine why your solver takes up so much RAM" You are right. This was the only true solution. I found the problem where I used to much memory. Thank you. – Vader Apr 25 '15 at 18:42
  • See http://stackoverflow.com/questions/2679330/catching-java-lang-outofmemoryerror – Raedwald Apr 02 '16 at 14:40

1 Answers1

3

Running out of memory is not an exception, it's an error -- a state from which your program is unlikely to recover. Errors are not exceptions, so catching exceptions doesn't work.

If you really want to catch it, use OutOfMemoryError:

try {
  expensiveMethod();
} catch (OutOfMemoryError e) {
  // ...
}

Note that if you catch this, what you're saying is, "I know how to handle a situation where I run out of memory". This is extremely unlikely to be true; your program is already in a precarious state, and any further allocations are probably going to trigger another OOME.

Is there a way to get more memory [...]?

The correct solution is to have your program use fewer resources at once. For example, you could chunk the work of your solver into discrete blocks, and incrementally store your work (e.g. by writing it to disk) when it gets too large. Later, when you want the final solution, load the resolved chunks back into memory and assemble them.

Is there a way [...] to stop the solver before the memory is full?

You can monitor your app's current memory usage:

MemoryInfo mi = new MemoryInfo();
ActivityManager a = (ActivityManager)getSystemService(ACTIVITY_SERVICE);
a.getMemoryInfo(mi);

and take some action based on that. But once you're actually out of memory, it's probably too late to do anything useful.

John Feminella
  • 303,634
  • 46
  • 339
  • 357