Подтвердить что ты не робот

Как использовать утечку канарейки

Я знаю, что это, наверное, немой вопрос, но я довольно новичок в разработке Android, и в настоящее время я испытываю OutOfMemoryError в своих приложениях, которые я пытался отлаживать с помощью MAT, но все равно слишком сложно найти утечку в нескольких действиях, тогда я нашел LeakCanary, который кажется более простым и простым в использовании, однако я не мог найти начального пошагового руководства по использованию Leak Canary даже в Google. Я установил LeakCanary через зависимости в моей build.gradle, и это то, что я получил до сих пор:

ExampleApplication.java

public class ExampleApplication extends Application {

    public static RefWatcher getRefWatcher(Context context) {
        ExampleApplication application = (ExampleApplication) context.getApplicationContext();
        return application.refWatcher;
    }

    private RefWatcher refWatcher;

    @Override
    public void onCreate() {
        super.onCreate();
        refWatcher = LeakCanary.install(this);
    }

    final class KeyedWeakReference extends WeakReference<Object> {
        public final String key;
        public final String name;

        KeyedWeakReference(Object referent, String key, String name,
                       ReferenceQueue<Object> referenceQueue) {
            super(checkNotNull(referent, "referent"), checkNotNull(referenceQueue, "referenceQueue"));
            this.key = checkNotNull(key, "key");
            this.name = checkNotNull(name, "name");
        }
    }

    public void watch(Object watchedReference, String referenceName) {
        checkNotNull(watchedReference, "watchReference");
        checkNotNull(referenceName, "referenceName");
        if(debuggerControl.isDebuggerAttached()) {
            return;
        }
        final long watchStartNanoTime = System.nanoTime();
        String key = UUID.randomUUID().toString();
        retainedKeys.add(key);
        final KeyedWeakReference reference =
            new KeyedWeakReference(watchedReference, key, referenceName, queue);
        watchExecutor.execute()

    }
}

Скажем, у меня есть Activity, где я хочу, чтобы LeakCanary просматривал объект

SampleActivity.java

public class SampleActivity extends Activity implements View.OnClickListener {
    ImageView level001, level002;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.choose_level);

        level001 = (ImageView) findViewById(R.id.level001);
        level002 = (ImageView) findViewById(R.id.level002);

        // Do all kinds of function
        // How do I use LeakCanary to watch these objects ?

    }
}

Теперь, как я могу использовать LeakCanary, чтобы увидеть, какой объект вызывает утечку памяти. Благодарим вас за помощь и помощь.

4b9b3361

Ответ 1

Хорошая вещь о канале утечки - как автоматизировано это работает. По умолчанию он уже "наблюдает" за действиями, которые не соответствуют GCed. Поэтому из коробки, если какая-либо активность протекает, вы должны получить уведомление.

В моем проекте я добавил дополнительный метод для Application следующим образом:

public class ExampleApplication extends Application {
    public static ExampleApplication instance;
    private RefWatcher refWatcher;

    @Override
    public void onCreate() {
        super.onCreate();
        instance = this;
        refWatcher = LeakCanary.install(this);
    }

    public void mustDie(Object object) {
        if (refWatcher != null) {
            refWatcher.watch(object);
        }
    }
}

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

Например, мы используем "базовый фрагмент" со следующим кодом:

@Override
public void onDestroy() {
    super.onDestroy();
    ExampleApplication.instance.mustDie(this);
}

таким образом LeakCanary пытается проверить, не протекает ли какой-либо фрагмент памяти.

Итак, для дальнейшего внедрения в вашем приложении вы можете/должны выполнять задачи или экземпляры, которые, как вы знаете, должны собирать мусор, но вы думаете, что это может быть не так, и вы не знаете, где вы можете это назвать: ExampleApplication.instance.mustDie(object);

а затем вы ДОЛЖНЫ запускать приложение и поворачивать устройство и вызывать утечку, поэтому утечка canary может захватить/проанализировать трассировку стека и дать вам ценную информацию о том, как ее исправить.

Надеюсь, это поможет.

Ответ 2

Я использовал здесь в приложении

import android.content.Context;
import android.support.multidex.MultiDex;
import android.support.multidex.MultiDexApplication;
import com.squareup.leakcanary.LeakCanary;
import com.squareup.leakcanary.RefWatcher;
import school.my.com.school.BuildConfig;

public class AppController extends MultiDexApplication {

private RefWatcher refWatcher;

public static RefWatcher getRefWatcher(Context context) {
    AppController application = (AppController) context.getApplicationContext();
    return application.refWatcher;
}



@Override
public void onCreate() {
    super.onCreate();
    if(BuildConfig.DEBUG)
        refWatcher = LeakCanary.install(this);

}

}

Вы можете использовать здесь Приложение вместо MultiDexApplication

Ответ 3

У меня был тот же вопрос о том, как использовать LeakCanary. Я просто хотел увидеть базовый пример того, как его запустить, и увидеть мой первый путь к утечке объекта.

Как использовать LeakCanary

Вот основной пример того, как работает LeakCanary:

Как использовать LeakCanary (4 минуты 13 секунд)

Одна из проблем, которую мне пришлось преодолеть, заключалась в том, чтобы выяснить, что мне нужно запускать приложение в обычном режиме запуска, а не в режиме отладки. Мне также пришлось отклониться от основных инструкций и установить файл build.gradle уровня build.gradle следующим образом:

dependencies {
  debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.5.4'
  releaseImplementation 'com.squareup.leakcanary:leakcanary-android:1.5.4'
}

Я думаю, что debugImplementation не работал для меня, потому что LeakCanary игнорирует обнаружение утечек при отладке. Хотя LeakCanary заявляет, что предоставляет версию "no-op" своей библиотеки для выпуска, так как отладка у меня не сработала, я изменил releaseImplementation выше с рекомендуемого com.squareup.leakcanary:leakcanary-android-no-op:1.5.4 в com.squareup.leakcanary:leakcanary-android:1.5.4.

Как вы можете видеть на видео, еще одна проблема, с которой мне приходилось сталкиваться, заключалась в предоставлении доступа на запись в LeakCanary. Я провела пальцем вниз и увидела уведомление от LeakCanary о том, что не удалось получить доступ для записи (подробнее). Я никогда не видел запрос на разрешение. Таким образом, в одном случае (не показанном на видео) я дал своему приложению доступ на запись, перейдя в приложение "Настройки", найдя мое приложение (в отличие от приложения под названием "Leak", которое устанавливает LeakCanary) и включив доступ для записи. В видео мне не нужно было этого делать, потому что я дал разрешение, ответив на уведомление. Затем во время использования моего приложения я периодически проверяю наличие новых уведомлений (проводя вниз). Я видел сообщения типа "Утечка XYZActivity 217 КБ". Я нажал на это, и это заняло меня в этом приложении Leak.

Кроме того, я заметил, что иногда анализ может занять до нескольких минут и отображать уведомление об утечке памяти на вашем телефоне.

Как проверить исправление утечки памяти с помощью LeakCanary

Теперь, когда я исправил некоторые утечки памяти, я использую LeakCanary для проверки исправления. Однако, если LeakCanary ничего не сообщает, я не обязательно верю в это, потому что моя утечка исправлена. Это может быть просто LeakCanary сломан.

Как проверить исправление утечки памяти с помощью LeakCanary (16 минут 34 секунды)

Процесс проверки утечки памяти с помощью LeakCanary: 1. Подтвердите утечку памяти с помощью LeakCanary 2. Исправьте утечку памяти и подтвердите, что LeakCanary сообщает об отсутствии утечек 3. Отмените исправление и подтвердите, что LeakCanary снова сообщает об утечке

Поскольку LeakCanary показывает очень мало информации о состоянии, когда он работает, трудно понять, что он вообще делает. Это привело меня к мысли, что я исправил утечку памяти, а на самом деле я этого не сделал. Три шага, описанные выше, являются лучшим способом проверки утечки памяти с помощью LeakCanary.

Ответ 4

Я использовал Leak-Canary, как показано ниже:

1) Зависимость Gradle:

debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.4'

2) Класс применения:

   @Override
public void onCreate() {
    super.onCreate();
    if (BuildConfig.DEBUG) {
        StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                .detectCustomSlowCalls()
                .detectNetwork()
                .penaltyLog()
                .penaltyDeath()
                .build());
        StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                .detectActivityLeaks()
                .detectLeakedClosableObjects()
                .detectLeakedRegistrationObjects()
                .detectLeakedSqlLiteObjects()
                .penaltyLog()
                .penaltyDeath()
                .build());

        LeakLoggerService.setupLeakCanary(this);
    }
}

3) Класс LeakLoggerService: поместите этот класс в пакет отладки, созданный gradle.

public class LeakLoggerService extends DisplayLeakService {

public static void setupLeakCanary(Application application) {
    if (LeakCanary.isInAnalyzerProcess(application)) {
        // This process is dedicated to LeakCanary for heap analysis.
        // You should not init your app in this process.
        return;
    }
    LeakCanary.install(application, LeakLoggerService.class,
            AndroidExcludedRefs.createAppDefaults().build());

}

@Override
protected void afterDefaultHandling(HeapDump heapDump, AnalysisResult result, String leakInfo) {
    if (!result.leakFound || result.excludedLeak) {
        return;
    }

    Log.w("LeakCanary", leakInfo);
}

4) Зарегистрировать сервис для манифеста файла и 1 разрешение:

  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
  <service android:name=".LeakLoggerService" />

5) Наконец, проверьте, если установка прошла успешно: утечка активности;)

public class Main2Activity extends AppCompatActivity {
static TextView label;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    label = new TextView(this);
    label.setText("asds");

    setContentView(label);
    if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 
}
}

убить это действие и проверить журналы с тегом: LeakCanary

Он должен работать...