2015-04-18 2 views
0

Я написал приложение для Android, где я реализовал решатель. Решатель выделяет много памяти. Для простых проблем это работает без проблем. Но когда проблема становится более сложной, я получаю сообщение об ошибке «Недостаточно памяти при распределении 2164 байт», и приложение выходит из строя.Как поймать OutOfMemoryError, прежде чем он сбой моего приложения?

Я пытался использовать

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

Но это не мешает приложение от сбой.

Я также пробовал "android:largeHeap="true" в AndroidManifest.xml.

Есть ли способ получить больше памяти или остановить решатель до того, как память будет заполнена?

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 
+0

«Но когда проблема усложняется, я получаю сообщение об ошибке« Недостаточно памяти при распределении по 2164 байтам », и приложение выходит из строя» - ваша куча фрагментирована настолько, что не более 2164 байт или более блоков доступная память. «Но это не мешает приложению сбой» - «OutOfMemoryError» не является «Исключением». [Это ошибка] (http://developer.android.com/reference/java/lang/OutOfMemoryError.html). «Есть ли способ получить больше памяти», а не от Android SDK. «или остановить решателя до того, как память заполнена?» - не конкретно. – CommonsWare

+0

В общем, вы можете использовать 'getMemoryClass()' или 'getLargeMemoryClass()' на 'ActivityManager', чтобы определить, насколько большой может быть ваша куча. Затем используйте это как руководство для того, сколько вы можете выделить, прежде чем вы, скорее всего, получите «OutOfMemoryError». Однако, вероятно, вам стоит подумать о том, чтобы попытаться определить, почему ваш решатель занимает так много ОЗУ. – CommonsWare

+0

«Тем не менее, вам, вероятно, стоит подумать о том, чтобы попытаться определить, почему ваш решатель занимает так много ОЗУ» Вы правы. Это было единственно верное решение. Я нашел проблему, в которой я использовал большую память. Спасибо. – Vader

ответ

3

Запуск из памяти не является исключением, это ошибка - состояние, из которого ваша программа вряд ли восстановится. Ошибки не являются исключениями, поэтому исключения catching не работают.

Если вы действительно хотите, чтобы поймать его, использовать OutOfMemoryError:

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

Обратите внимание, что если вы ловите это, что вы говорите, «Я знаю, как справиться с ситуацией, когда я бегу из памяти ». Это невероятно маловероятно; ваша программа уже находится в неустойчивом состоянии, и любые дальнейшие распределения, вероятно, вызовут еще один OOME.

Есть ли способ получить больше памяти [...]?

Правильное решение заключается в том, чтобы ваша программа использовала меньше ресурсов одновременно. Например, вы можете разбить работу вашего решателя на отдельные блоки и постепенно сохранять свою работу (например, записывая ее на диск), когда она становится слишком большой. Позже, когда вы хотите окончательное решение, загрузите разрешенные куски обратно в память и соберите их.

Есть ли способ [...] остановить решатель до того, как память будет заполнена?

Вы можете отслеживать текущее использование памяти вашего приложения:

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

и принять некоторые действия, основанные на этом. Но как только вы на самом деле потеряете память, вероятно, слишком поздно делать что-нибудь полезное.

Смежные вопросы