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

J'ai eu quelques rapports des utilisateurs de crashs lorsque j'utilise mon application sur 4G / LTE de Verizon.

En regardant la trace de la pile, il semble que l'application HttpClient.execute () de Android lance un OOM. Cela se produit uniquement sur les appareils 4G / LTE, en particulier HTC Thunderbolt, et uniquement sur les 4G / LTE. WiFi, 3G, UMTS sont OK. Fonctionne également bien sur le WiMax 4G de Sprint, ça marche bien.

  • Comment se déplacer vers le centre de l'enfance de HorizontalScrollView?
  • Exécuter le code dans le thread principal d'un autre thread
  • Eclipse ne présente pas la fenêtre du gestionnaire Avd et le projet Android
  • Android: Comment puis-je mettre en œuvre un premier didacticiel comme Go Launcher dans mon application?
  • Comment générer google-services.json pour le projet Google Android existant?
  • AccountManagerFuture.getResult () donne lieu à l'écran "Impossible de se connecter"
  • Deux questions:

    • Quelle est la meilleure façon d'attirer l'attention des développeurs d'Android à propos de cela? Toutes les meilleures options que les rapports sur http://code.google.com/p/android/issues ?

    • Des idées sur la façon dont je peux m'en occuper? Je n'ai pas un périphérique 4G moi-même et je ne peux pas arriver que cela se produise dans l'émulateur, alors j'ai besoin de faire des suppositions éduquées ici. Je peux essayer d'attraper l'OOM dans mon code et tenter de nettoyer et de forcer GC, mais je ne sais pas si c'est une bonne idée. Des commentaires ou d'autres suggestions?

    Voici ce que fait mon code:

    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 ); ... 

    Voici la trace de la pile qui s'écrase:

    E / dalvikvm-heap (11639): Mémoire insuffisante sur une allocation de 2055696-octets. 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 sched = 0/0 cgrp = handle par défaut = 3948760 I / dalvikvm (11639): | Schedstat = (208709711 74005130 214)

    I / dalvikvm (11639): à org.apache.http.impl.io.AbstractSessionInputBuffer.init (AbstractSessionInputBuffer.java:~79) I / dalvikvm (11639): à org.apache.http.impl.io.SocketInputBuffer. ( SocketInputBuffer.java:93) I / dalvikvm (11639): à org.apache.http.impl.SocketHttpClientConnection.createSessionInputBuffer (SocketHttpClientConnection.java:83) I / dalvikvm (11639): à org.apache.http.impl.conn. DefaultClientConnection.createSessionInputBuffer (DefaultClientConnection.java:170) I / dalvikvm (11639): à org.apache.http.impl.SocketHttpClientConnection.bind (SocketHttpClientConnection.java:106) I / dalvikvm (11639): à org.apache.http. Impl.conn.DefaultClientConnection.openCompleted (DefaultClientConnection.java:129) I / dalvikvm (11639): à org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection (DefaultClientConnectionOperator.java:173) I / dalvikvm (11639): à Org.apache.http.impl.conn.AbstractPoolEntry.open (AbstractPoolEntry.java:164) I / dalvikvm (11639): à org.apache.http.impl.conn.AbstractPooledC OnnAdapter.open (AbstractPooledConnAdapter.java:119) I / dalvikvm (11639): à org.apache.http.impl.client.DefaultRequestDirector.execute (DefaultRequestDirector.java:348) I / dalvikvm (11639): à l'org.apache. Http.impl.client.AbstractHttpClient.execute (AbstractHttpClient.java:555) I / dalvikvm (11639): à org.apache.http.impl.client.AbstractHttpClient.execute (AbstractHttpClient.java:487) I / dalvikvm (11639) : À org.apache.http.impl.client.AbstractHttpClient.execute (AbstractHttpClient.java:465) I / dalvikvm (11639): à com.myapplication.Fetcher.trySourceFetch (Fetcher.java:205) I / dalvikvm (11639) : À com.myapplication.Fetcher.run (Fetcher.java:298) I / dalvikvm (11639): à java.lang.Thread.run (Thread.java: 1102) I / dalvikvm (11639): E / dalvikvm (11639) ): Mémoire insuffisante: Taille du tas = 24171KB, Attribué = 23142KB, Bitmap Taille = 59KB, Limite = 21884KB E / dalvikvm (11639): Informations supplémentaires: Empreinte = 24327KB, Empreinte autorisée = 24519KB, Découpe = 348KB W / dalvikvm (11639 ): Threadid = 9: thread sortant avec exception non captée (group = 0x40025b38)

  • Comment déterminer si le type de réseau est 2G, 3G ou 4G
  • Déterminez si LTE est activé?
  • Comment vérifier si un périphérique particulier prend en charge les réseaux 4G dans Android?
  • 3 Solutions collect form web for “Android HttpClient OOM sur 4G / LTE (HTC Thunderbolt)”

    En regardant la trace de la pile, il semble que l'application HttpClient.execute () de Android lance un OOM.

    Cela n'est pas indiqué par la trace de la pile que vous avez sur le problème. Bien sûr, vous n'avez pas fourni la trace complète de la pile sur le problème.

    Quelle est la meilleure façon d'attirer l'attention des développeurs d'Android à propos de cela? Toutes les meilleures options que les rapports sur http://code.google.com/p/android/issues ?

    La probabilité que ce soit un simple bogue Android soit petit, mais pas zéro.

    Voici d'autres possibilités, sans ordre particulier:

    1. Il n'y a pas de problème avec execute() per se, mais que vous vous enlevez simplement de la mémoire, et les traces de pile que vous avez rencontrées démontrent simplement que execute() accentue votre tas.

    2. Le problème est dans certaines modifications que HTC a faites à Android pour le Thunderbolt, peut-être uniquement en fonction du réseau LTE.

    3. Le problème est en quelque sorte causé par le réseau Verizon LTE lui-même (p. Ex., Un proxy de leur envoi d'informations visball qui cause HttpClient pour avoir une conniption).

    Des idées sur la façon dont je peux m'en occuper?

    Tout d'abord, j'utiliserais les outils existants (p. Ex., Vidange de HPROF et examen avec Eclipse MAT) afin de confirmer que vous n'avez pas de fuite de mémoire en général que le combo Thunderbolt / LTE semble simplement se débrouiller.

    Ensuite, je vous recommande de trouver une manière cohérente de reproduire l'erreur. Cela pourrait être votre application existante avec une série d'étapes à suivre, ou il pourrait s'agir d'une application dédiée (par exemple, enregistrer l'URL qui déclenche l'OOM, puis créer une petite application qui fait exactement cette requête HttpClient). J'aimerais que DeviceAnywhere ait un Thunderbolt, mais ça ne ressemble pas à ça. Je vais mettre des feux et voir si je peux obtenir de l'aide sur ce front.

    En ce qui concerne le fonctionnement de celui-ci, en tant que bit d'arrêt, vous pouvez détecter que vous utilisez un Thunderbolt via android.os.Build données, et peut-être que vous êtes sur LTE via ConnectivityManager (je suppose que LTE serait listé comme WiMAX , Mais c'est juste une supposition), et avertir les utilisateurs des problèmes avec ce combo.

    Au-delà, vous pouvez essayer de modifier votre utilisation HttpClient un peu et voir si cela a un effet, par exemple:

    • Si vous ne supportez que l'API au niveau 8 ou supérieur, vous pourriez donner à AndroidHttpClient une prise de vue en remplacement
    • Désactivez l'accès multi-thread (en général ou Thunderbolt-specific) et débarrassez-vous du ThreadSafeClientConnManager

    Je suis désolé de ne pas avoir une réponse «balle magique» pour vous ici.


    METTRE À JOUR

    Maintenant que j'ai la trace complète de la pile, regarder à travers le code source est … éclairant un peu.

    Le problème semble être que:

     HttpConnectionParams.getSocketBufferSize(params); 

    Renvoie cette valeur de 2 Mo ou qui déclenche l'OOM. C'est un tampon terriblement grand, en particulier pour le moteur Dalvik GC, qui peut être fragmenté (oui, il y a encore ce mot).

    params ici est le HttpParams . Vous semblez créer ces vous-même via getHttpParams() . Par exemple, AndroidHttpClient définit cela à 8192:

     HttpConnectionParams.setSocketBufferSize(params, 8192); 

    Si vous définissez la taille du tampon de socket vous-même, essayez de le réduire. Sinon, essayez de le configurer sur 8192 et de voir si cela vous aide.

    Voici la solution: https://review.source.android.com/22852

    En attendant, URLConnection est immunisée. C'est le seul HttpClient qui a ce problème.

    Si vous êtes un développeur qui souhaite tester ce type d'échec, vous pouvez utiliser "adb shell setprop" pour définir, par exemple, "net.tcp.buffersize.wifi" afin que les tailles de tampon de socket de lecture / écriture maximales soient énormes lorsque votre L'appareil est sur wifi. Quelque chose comme ce qui suit serait un véritable test de stress:

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

    C'est ce genre de changement de configuration qui exerce le bogue HttpClient. Je ne sais pas quelles sont les valeurs exactes sur le Thunderbolt, mais quelqu'un avec l'appareil pourrait trouver en utilisant "adb shell getprop | grep buffersize".

    Peut-être que cela aidera:

     // 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); 
    coAndroid est un fan Android de Google, tout sur les téléphones Android, Android Wear, Android Dev et Android Games Apps.