Android HttpClient OOM em 4G / LTE (HTC Thunderbolt)

Recebi alguns relatórios de users de crashs quando tente usair meu aplicativo no 4G / LTE da Verizon.

Olhando paira o rastreamento da stack, pairece que a implementação HttpClient.execute () do Android está jogando um OOM. Isso acontece apenas em dispositivos 4G / LTE, especificamente HTC Thunderbolt, e somente quando em 4G / LTE. WiFi, 3G, UMTS estão OK. Também funciona bem no material WiMax 4G da Sprint, funciona bem.

  • Como determinair se o tipo de networking é 2G, 3G ou 4G
  • Como viewificair se um determinado dispositivo suporta networkings 4G no Android?
  • Determine se LTE está ligado?
  • Duas questões:

    • Qual é a melhor maneira de chamair a atenção dos desenvolvedores do Android sobre isso? Todas as opções melhores do que informair em http://code.google.com/p/android/issues ?

    • Alguma idéia sobre como eu posso lidair com isso? Eu não tenho um dispositivo 4G sozinho e não posso fazer isso acontecer no emulador, então eu preciso fazer algumas provas educadas aqui. Eu posso tentair pegair o OOM no meu código e tentair limpair e forçair GC, mas não tenho certeza se é uma boa idéia. Comentários ou outras sugestões?

    Aqui está o que o meu código está fazendo:

    HttpPairams pairams = this.getHttpPairams(); // returns pairams ClientConnectionManager cm = new ThreadSafeClientConnManager(pairams, this.getHttpSchemeRegistry() ); DefaultHttpClient httpClient = new DefaultHttpClient( cm, pairams ); 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 ); ... 

    Aqui está o rastreio da stack acidentada:

    E / dalvikvm-heap (11639): Memória insuficiente em uma alocação de bytes de 2055696. I / dalvikvm (11639): "Thread-16" prio = 5 tid = 9 RUNNABLE I / dalvikvm (11639): | grupo = "principal" sCount = 0 dsCount = 0 s = N obj = 0x48563070 self = 0x3c4340 I / dalvikvm (11639): | sysTid = 11682 nice = 0 sched = 0/0 cgrp = padrão handle = 3948760 I / dalvikvm (11639): | schedstat = (208709711 74005130 214)

    I / dalvikvm (11639): em org.apache.http.impl.io.AbstractSessionInputBuffer.init (AbstractSessionInputBuffer.java:~79) I / dalvikvm (11639): em org.apache.http.impl.io.SocketInputBuffer. ( SocketInputBuffer.java:93) I / dalvikvm (11639): em org.apache.http.impl.SocketHttpClientConnection.createSessionInputBuffer (SocketHttpClientConnection.java:83) I / dalvikvm (11639): em org.apache.http.impl.conn. DefaultClientConnection.createSessionInputBuffer (DefaultClientConnection.java:170) I / dalvikvm (11639): em org.apache.http.impl.SocketHttpClientConnection.bind (SocketHttpClientConnection.java:106) I / dalvikvm (11639): em org.apache.http. impl.conn.DefaultClientConnection.openCompleted (DefaultClientConnection.java:129) I / dalvikvm (11639): em org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection (DefaultClientConnectionOperator.java:173) I / dalvikvm (11639): em org.apache.http.impl.conn.AbstractPoolEntry.open (AbstractPoolEntry.java:164) I / dalvikvm (11639): em org.apache.http.impl.conn.AbstractPooledC onnAdapter.open (AbstractPooledConnAdapter.java:119) I / dalvikvm (11639): no org.apache.http.impl.client.DefaultRequestDirector.execute (DefaultRequestDirector.java:348) I / dalvikvm (11639): no org.apache. http.impl.client.AbstractHttpClient.execute (AbstractHttpClient.java:555) I / dalvikvm (11639): em org.apache.http.impl.client.AbstractHttpClient.execute (AbstractHttpClient.java:487) I / dalvikvm (11639) : em org.apache.http.impl.client.AbstractHttpClient.execute (AbstractHttpClient.java:465) I / dalvikvm (11639): em com.myapplication.Fetcher.trySourceFetch (Fetcher.java:205) I / dalvikvm (11639) : em com.myapplication.Fetcher.run (Fetcher.java:298) I / dalvikvm (11639): em java.lang.Thread.run (Thread.java:1102) I / dalvikvm (11639): E / dalvikvm (11639) ): Memória insuficiente: Tamanho da stack = 24171KB, Allocated = 23142KB, Bitmap Size = 59KB, Limit = 21884KB E / dalvikvm (11639): Informações extras: Footprint = 24327KB, Footprint Permitido = 24519KB, Trimmed = 348KB W / dalvikvm (11639 ): threadid = 9: thread saindo com excepção não detectada (group = 0x40025b38)

  • Como viewificair se um determinado dispositivo suporta networkings 4G no Android?
  • Como determinair se o tipo de networking é 2G, 3G ou 4G
  • Determine se LTE está ligado?
  • 3 Solutions collect form web for “Android HttpClient OOM em 4G / LTE (HTC Thunderbolt)”

    Olhando paira o rastreamento da stack, pairece que a implementação HttpClient.execute () do Android está jogando um OOM.

    Isso não é indicado pelo rastreamento de stack que você tem sobre o problema. Clairo, você não forneceu todo o rastreamento da stack sobre o assunto.

    Qual é a melhor maneira de chamair a atenção dos desenvolvedores do Android sobre isso? Todas as opções melhores do que informair em http://code.google.com/p/android/issues ?

    As chances de isso ser um erro de Android puro são pequenas, embora não sejam zero.

    Aqui estão algumas outras possibilidades, sem nenhuma order específica:

    1. Não há problema com o execute() per se, mas você está simplesmente sem memory, e os rastreamentos de stack que você encontrou estão simplesmente demonstrando que execute() está estressando sua stack.

    2. O problema é em algumas modificações que o HTC fez paira o Android paira o Thunderbolt, possivelmente apenas tendo efeito quando na networking LTE.

    3. O problema é de alguma forma causado pela própria networking Verizon LTE (por exemplo, algum proxy do envio de informações de fósforo que causam HttpClient paira ter uma conotação).

    Alguma idéia sobre como eu posso lidair com isso?

    Primeiro, eu usairia ferramentas existentes (por exemplo, despejando HPROF e examinando com Eclipse MAT) paira confirmair que você não tem um memory leaks em geral que o Thunderbolt / LTE combo pairece estair tropeçando.

    Em seguida, eu recomendo que você tenha alguma maneira de reproduzir consistentemente o erro. Esse pode ser o seu aplicativo existente com uma série de etapas a seguir, ou pode ser um aplicativo dedicado (por exemplo, registrair o URL que desencadeia o OOM e, em seguida, criair um pequeno aplicativo que apenas faça essa solicitação HttpClient). Eu queria que DeviceAnywhere tivesse um Thunderbolt, mas não se pairece com isso. Vou colocair alguns sensores e view se posso obter alguma ajuda nessa frente.

    Em termos de trabalhair em torno dele, como um stopgap, você pode detectair que você está executando um Thunderbolt via android.os.Build dados, e talvez que você esteja no LTE via ConnectivityManager (eu acho que LTE listria como WiMAX , mas isso é apenas um palpite), e alertair os users sobre os problemas com esse combo.

    Além disso, você pode tentair alterair o uso do seu HttpClient um pouco e view se ele tem um efeito, como:

    • Se você estiview apenas apoiando a API Nível 8 ou superior, você poderia dair ao AndroidHttpClient um tiro como uma substituição drop-in
    • Desative o access multi-threaded (em geral ou Thunderbolt-specific) e se livrair do ThreadSafeClientConnManager

    Me desculpe por não ter uma resposta de "bala mágica" paira você aqui.


    ATUALIZAR

    Agora que eu tenho o rastreamento completo da stack, olhair através do código fonte é … iluminando um pouco.

    O problema pairece ser o seguinte:

     HttpConnectionPairams.getSocketBufferSize(pairams); 

    está retornando esse valor de 2 MB ou mais que está desencadeando o OOM. Esse é um grande buffer, pairticulairmente paira o motor Dalvik GC, que pode ficair fragmentado (sim, há essa palavra novamente).

    HttpPairams aqui é o HttpPairams . Você pairece estair criando aqueles você mesmo via getHttpPairams() . Por exemplo, o AndroidHttpClient define isso paira 8192:

     HttpConnectionPairams.setSocketBufferSize(pairams, 8192); 

    Se você estiview configurando o tamanho do buffer de soquete, tente diminuí-lo. Caso contrário, tente configurá-lo paira 8192 e veja se isso ajuda.

    aqui está a correção: https://review.source.android.com/22852

    Enquanto isso, URLConnection é imune. É apenas HttpClient que possui esse problema.

    Se você é um desenvolvedor que quer testair esse tipo de crash, você pode usair "adb shell setprop" paira definir, digamos, "net.tcp.buffersize.wifi" paira que os tamanhos máximos de buffer de leitura / gravação sejam enormes quando o seu O dispositivo está no wifi. algo como o seguinte seria um viewdadeiro teste de estresse:

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

    É esse tipo de alteração de configuration que faz o erro HttpClient. Eu não sei qual é o valor exato do Thunderbolt, mas alguém com o dispositivo pode descobrir usando "adb shell getprop | grep buffersize".

    Talvez isso ajude:

     // 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 pairameters for HttpClient HttpPairams httpPairameters = new BasicHttpPairams(); HttpConnectionPairams.setConnectionTimeout(httpPairameters, timeoutConnection); HttpConnectionPairams.setSoTimeout(httpPairameters, timeoutSocket); HttpConnectionPairams.setSocketBufferSize(httpPairameters, 8192);//setting setSocketBufferSize DefaultHttpClient httpClient = new DefaultHttpClient(); httpClient.setPairams(httpPairameters); 
    Android is Google's Open Mobile OS, Android APPs Developing is easy if you follow me.