Вопрос

Я получил несколько отчетов от пользователей сбоев, когда попробую использовать мое приложение на 4G/LTE Verizon.

Глядя на трассировку стека, похоже, что реализация Android httpclient.execute () бросает OOM. Это происходит только на устройствах 4G/LTE, в частности HTC Thunderbolt, и только на 4G/LTE. Wi -Fi, 3G, UMTS в порядке. Также отлично работает на материалах Sprint Wimax 4G работает нормально.

Два вопроса:

  • Как лучше всего привлечь внимание Android Devs об этом? Какие -либо лучшие варианты, чем отчет о http://code.google.com/p/android/issues?

  • Есть идеи о том, как я могу обойти это? У меня нет устройства 4G, и я не могу получить это в эмуляторе, поэтому мне нужно сделать здесь несколько образованных догадок. Я могу попытаться поймать OOM в своем коде и попытаться очистить и заставить GC, но я не уверен, хорошая ли это идея. Комментарии или другие предложения?

Вот что делает мой код:

    HttpParams params = this.getHttpParams(); // returns params
    ClientConnectionManager cm = new ThreadSafeClientConnManager(params, this.getHttpSchemeRegistry() );
    DefaultHttpClient httpClient = new DefaultHttpClient( cm, params );

    HttpResponse response = null;
    request = new HttpGet( url );

    try {

        response = httpClient.execute(request); // <-- OOM on 4G/LTE. OK otherwise
        int statusCode = response.getStatusLine().getStatusCode();
        Log.i("fetcher", "execute returned, http status " + statusCode );

    ...

Вот сбой трассировки стека:

E/dalvikvm-heap (11639): вне памяти при распределении 2055696-байтовых. I/dalvikvm (11639): "Thread-16" Prio = 5 Tid = 9 Runnable i/dalvikvm (11639): | Group = "main" scount = 0 dscount = 0 s = n obj = 0x48563070 self = 0x3c4340 i/dalvikvm (11639): | Systid = 11682 NICE = 0 SHAD = 0/0 CGRP = Руководство по умолчанию = 3948760 I/DALVIKVM (11639): | schedstat = (208709711 74005130 214)

I/dalvikvm (11639): at org.apache.http.impl.io.abstractsessionInputBuffer.init (AbstractSessionInputBuffer.java:~79) i/dalvikvm (11639): at org.apache.http.impl.io.socketinputBuffer. SocketInputBuffer.java:93) i/dalvikvm (11639): at org.apache.http.impl.sockethttpclientconnection.createsessionInputBuffer (sockethttpclientConcection.java:83) i/dalvikvm (11639): at org.htt. DefaultClientConnection.createsessionInputBuffer (defaultClientConnection.java:170) i/dalvikvm (11639): at org.apache.http.impl.sockethttpclientconnection.bind (sockethtpclientConcection.java:106) i/dalvik. Impl.conn.defaultclientConnection.openceploteed (defaultClientConnection.java:129) I/dalvikvm (11639): at org.apache.http.impl.conn.defaultclientConnectionoperator.openconconce (defaultconconceperator.javavac org.apache.http.impl.conn.abstractpoolentry.open (AbstractPoolEntry.java:164) i/dalvikvm (11639): at org.apache.http.impl.conn.abstractpooledc onnadapter.open (AbstractPooledConnadapter.java:119) i/dalvikvm (11639): at org.apache.http.impl.client.defaultrequestdirector.execute (defaultrequestdirector.java:348) i/dalvikvm (11639): http.impl.client.abstracthttpclient.execute (actractttpclient.java:555) i/dalvikvm (11639): at org.apache.http.impl.client.abstracthttpclient.execute (agesttttpclient.java:487) i/dal -execute (agesttttpclient.java:487)) i/dal -execute (agesttttpclient.java:487))) (Abstractttpclient.java:487))) (Abstractttpclient.java:487))) (Abstractttpclient.java:487)))) : at org.apache.http.impl.client.abstracthttpclient.execute (Abstractttpclient.java:465) i/dalvikvm (11639): at com.myapplication.fetcher.trysourcefetch (fetcher.java:205) i/dalvikvm (11639) (11639) (11639). : at com.myapplication.fetcher.run (fetcher.java:298) i/dalvikvm (11639): at java.lang.thread.run (Thread.java:1102) i/dalvikvm (11639): e/dalvikvm (11639 ): Из памяти: размер кучи = 24171 КБ, выделенная = 23142 КБ, размер растрового изображения = 59 КБ, предел = 21884KB E/Dalvikvm (11639): дополнительная информация: FootPrint = 24327KB, разрешенный спред = 24519KB, TRIMMED = 348KB W/DALVIKVM = 24519KB, TRIMMED = 348KB W/DALVIKVM (116399KB, TRIMMED = 348KB W/DALVIKVM (116399KB, TRIMMED = 348KB W/DALVIKVM (116399KB, TRIMMED = 348KB W/DALVIKVM (11639. ): ThreadId = 9: поток выходит с исключением Uncaught (Group = 0x40025B38)

Это было полезно?

Решение

Глядя на трассировку стека, похоже, что реализация Android httpclient.execute () бросает OOM.

Это не обозначено трассировкой стека, который у вас есть по этому вопросу. Конечно, вы не предоставили всю трассу стека по этому вопросу.

Как лучше всего привлечь внимание Android Devs об этом? Какие -либо лучшие варианты, чем отчет о http://code.google.com/p/android/issues?

Шансы на это чистая ошибка Android маленькие, хотя и не нулевые.

Вот некоторые другие возможности, в любом случае:

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

  2. Проблема заключается в некоторых модификациях, которые HTC сделал для Android для Thunderbolt, возможно, вступает в силу только в сети LTE.

  3. Эта проблема каким -то образом вызвана самой сетью Verizon LTE (например, некоторая их прокси -сервера, отправляющая информацию о винтовом шаре, которая заставляет httpclient иметь Contiption).

Есть идеи о том, как я могу обойти это?

Во -первых, я бы использовал существующие инструменты (например, сбрасывание HPROF и осмотр с помощью Mat Mat), чтобы подтвердить, что у вас нет утечки памяти в целом, что комбинация Thunderbolt/LTE, кажется, просто споткнулась.

Далее я рекомендую вам придумать какой -то способ последовательно воспроизводить ошибку. Это может быть ваше существующее приложение с серией шагов, которые нужно следовать, или это может быть выделенное приложение (например, зарегистрировать URL, который запускает OOM, а затем создайте крошечное приложение, которое просто выполняет этот запрос HTTPClient). Я бы хотел, чтобы у Deviceany было громопровод, но это не похоже на это. Я выложу некоторые чувства и посмотрю, смогу ли я получить некоторую помощь на этом фронте.

С точки зрения работы вокруг этого, как остановка, вы можете обнаружить, что вы работаете на Thunderbolt через android.os.Build данные, и, возможно, вы находитесь на LTE через ConnectivityManager (Я предполагаю, что LTE будет перечислять как Wimax, но это просто предположение) и предупреждает пользователей о проблемах с этим комбо.

Кроме того, вы можете немного изменить свое использование HTTPClient и посмотреть, имеет ли оно влияние, например:

  • Если вы поддерживаете только уровень API уровня 8 или выше, вы можете дать AndroidHttpClient выстрел в качестве замены
  • Отключить многопоточный доступ (в целом или специфичный для молнии) и избавиться от ThreadSafeClientConnManager

Мне жаль, что у меня нет ответа «волшебная пуля» для вас здесь.


ОБНОВИТЬ

Теперь, когда у меня есть полная трассировка стека, просмотр исходного кода ... немного освещает.

Проблема, по -видимому, заключается в том, что:

HttpConnectionParams.getSocketBufferSize(params);

возвращает это значение 2 МБ или около того, которое запускает OOM. Это ужасно большой буфер, особенно для двигателя Dalvik GC, который может быть фрагментирован (да, есть это слово снова).

params здесь HttpParams. Анкет Вы, кажется, создаете их сами через getHttpParams(). Анкет Например, AndroidHttpClient устанавливает это на 8192:

HttpConnectionParams.setSocketBufferSize(params, 8192);

Если вы сами устанавливаете размер буфера сокета, попробуйте уменьшить его. Если нет, попробуйте установить его на 8192 и посмотрите, поможет ли это.

Другие советы

Вот исправление: https://review.source.android.com/22852

В то же время, UrlConnection является невосприимчивым. Это только httpclient, который имеет эту проблему.

Если вы разработчик, который хотите проверить этот вид сбоев, вы можете использовать «ADB Shell SetProp», чтобы установить, скажем, «net.tcp.buffersize.wifi», чтобы максимальные размеры буфера для чтения/записи огромные, когда ваши Устройство на Wi -Fi. Что -то вроде следующего было бы реальным стрессовым тестом:

adb shell setprop net.tcp.buffersize.wifi 4096,80999999,80999999,4096,80999999,80999999

Это изменение конфигурации, которое осуществляет ошибку HTTPClient. Я не знаю, каковы точные значения на Thunderbolt, но кто -то с устройством мог бы узнать, используя «ADB GetProp | Grep Buffersize».

Может, это поможет:

// Set the timeout in milliseconds until a connection is established.
int timeoutConnection = 5000;

// Set the default socket timeout (SO_TIMEOUT) 
// in milliseconds which is the timeout for waiting for data.
int timeoutSocket = 4000;

// set timeout parameters for HttpClient 
HttpParams httpParameters = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
HttpConnectionParams.setSocketBufferSize(httpParameters, 8192);//setting setSocketBufferSize

DefaultHttpClient httpClient = new DefaultHttpClient();
httpClient.setParams(httpParameters);
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top