leakcanary는android8에 있습니다.0의 작은 실험

4121 단어
leakcanary 소형 실험
조사 연구 leakcanary 참조 링크는 다음과 같습니다.https://www.liaohuqiu.net/cn/posts/leak-canary-read-me/https://github.com/square/leakcanaryleakcanary는android 메모리 유출 모니터링 도구로 약한 인용 대기열을 이용한다.작업 메커니즘은 다음과 같다. 작업 절차1.RefWatcher.watch () 는 감시할 대상에 KeyedWeakReference를 만듭니다.2. 백엔드 라인에서 인용이 삭제되었는지 확인하고 없으면 GC를 호출합니다.3. 인용이 삭제되지 않으면 APP에 대응하는 파일 시스템 중 하나에 heap 메모리 덤프를 넣습니다.hprof 파일에서4. 다른 프로세스의 HeapAnalyzer Service에는 HAHA를 사용하여 파일을 처리하는 HeapAnalyzer가 있습니다.5. 유일한 Reference 키 덕분에 Heap Analyzer가 Keyed Weak Reference를 찾아 메모리 유출을 포지셔닝했다.6. HeapAnalyzer는 GC 루트의 가장 짧은 참조 경로를 계산하고 유출 여부를 확인합니다.그렇다면 유출을 초래하는 인용체인을 구축한다.7. 인용체인이 앱 프로세스에 전달된 DisplayLeakService를 알림 형식으로 보여준다.
사용 과정 중build을 설정합니다.gradle (당신의 앱이 전역적이지 않다는 것을 주의하십시오)
dependencies{
    debugImplementation 'com.squareup.leakcanary:leakcanary-android:1.6.3'
    releaseImplementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.6.3'
}

실험 코드는 다음과 같다. 정적 대상이 일으킨 메모리 유출(사용자 정의 대상의 모니터링, 응용 프로그램을 스스로 계승해야 함)
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import com.squareup.leakcanary.*;

class Cat {
    String name;
    Cat(String _name){
        name=_name;
    }
}
class Box {
    Cat hiddenCat;
}
class schrodinger{
    static Box hisbox;
}
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Box box = new Box();
        Cat schrodingerCat = new Cat("caffe");
        box.hiddenCat = schrodingerCat;
        schrodinger.hisbox = box;
        RefWatcher ref = myapplication.getRefWatcher(this);
        ref.watch(schrodingerCat);
    }
}

leakcanary 중 일부 코드 분석:watch 방법:
@Synchronized fun watch(
    watchedReference: Any,
    referenceName: String
  ) {
    removeWeaklyReachableReferences()
    //     
    val key = UUID.randomUUID()
        .toString()
    //         key
    val watchUptimeMillis = clock.uptimeMillis()
    //    
    val reference =
      KeyedWeakReference(watchedReference, key, referenceName, watchUptimeMillis, queue)
    //     
    if (referenceName != "") {
      CanaryLog.d(
          "Watching instance of %s named %s with key %s", reference.className,
          referenceName, key
      )
    } else {
      CanaryLog.d(
          "Watching instance of %s with key %s", reference.className, key
      )
    }
    watchedReferences[key] = reference
    //   map     key        
    checkRetainedExecutor.execute {
      moveToRetained(key)
    }
  }

누설 모니터링:
fun detectLeaks(): Result {
    val leakDetectionTime = SystemClock.uptimeMillis()
    val watchDurationMillis = LeakSentry.config.watchDurationMillis
    val instrumentation = getInstrumentation()
    val context = instrumentation.targetContext
    val refWatcher = LeakSentry.refWatcher
    if (!refWatcher.hasWatchedReferences) {
      return NoAnalysis
    }
    instrumentation.waitForIdleSync()
    if (!refWatcher.hasWatchedReferences) {
      return NoAnalysis
    }
    runGc()//   GC
    if (!refWatcher.hasWatchedReferences) {
      return NoAnalysis
    }
    // Waiting for any delayed UI post (e.g. scroll) to clear. This shouldn't be needed, but
    // Android simply has way too many delayed posts that aren't canceled when views are detached.
    SystemClock.sleep(2000)
    if (!refWatcher.hasWatchedReferences) {
      return NoAnalysis
    }
    // Aaand we wait some more.
    // 4 seconds (2+2) is greater than the 3 seconds delay for
    // FINISH_TOKEN in android.widget.Filter
    SystemClock.sleep(2000)
    val endOfWatchDelay = watchDurationMillis - (SystemClock.uptimeMillis() - leakDetectionTime)
    if (endOfWatchDelay > 0) {
      SystemClock.sleep(endOfWatchDelay)
    }
    runGc()//   GC
    if (!refWatcher.hasRetainedReferences) {
      return NoAnalysis
    }
    //  dump...    
}

전재 대상:https://www.cnblogs.com/zhangxianlong/p/10720197.html

좋은 웹페이지 즐겨찾기