9

私は Android アプリに取り組んでおり、メモリ使用量を調査しています。

hprof からのヒープ ダンプを見ると、JarURLConnectionImpl の静的キャッシュで約 2M (ヒープの 22%) が使用されていることがわかります。

ここに画像の説明を入力

JarURLConnectionImplのソース コードを見ると、静的 jarCache 変数にエントリが追加されているように見えますが、削除されていません。

それらが決して削除されないことが本当なら、それはメモリリークの可能性があると思います。

これは漏れですか?修正または回避策はありますか?

4

2 に答える 2

5

これは醜い回避策です:

private static HashMap<URL,JarFile> jarCache;


static {
    try {
        Class<?> jarURLConnectionImplClass = Class.forName("org.apache.harmony.luni.internal.net.www.protocol.jar.JarURLConnectionImpl");
        final Field jarCacheField = jarURLConnectionImplClass.getDeclaredField("jarCache");
        jarCacheField.setAccessible(true);
        //noinspection unchecked
        jarCache = (HashMap<URL, JarFile>) jarCacheField.get(null);
    } catch(Exception e) {
        // ignored
    }
}

次に、定期的に次を実行します。

    // HACK http://stackoverflow.com/questions/14610350/android-memory-leak-in-apache-harmonys-jarurlconnectionimpl
    if( jarCache!=null ) {
        try {
            for (
                final Iterator<Map.Entry<URL, JarFile>> iterator = jarCache.entrySet().iterator(); iterator.hasNext(); ) {
                final Map.Entry<URL, JarFile> e = iterator.next();
                final URL url = e.getKey();
                if (Strings.toString(url).endsWith(".apk")) {
                    Log.i(TAG,"Removing static hashmap entry for " + url);
                    try {
                        final JarFile jarFile = e.getValue();
                        jarFile.close();
                        iterator.remove();
                    } catch( Exception f ) {
                        Log.e(TAG,"Error removing hashmap entry for "+ url,f);
                    }
                }
            }
        } catch( Exception e ) {
            // ignored
        }
    }

アクティビティの作成時に実行するので、アクティビティの 1 つが作成されるたびに実行されます。醜いハッシュマップ エントリはそれほど頻繁に再作成されるようには見えませんが、ときどき再表示されるように思われるため、このコードを 1 回実行するだけでは十分ではありません。

于 2013-02-01T00:29:09.427 に答える