LeakCanary-源码篇

本篇主要介绍LeakCanary的执行流程,一些具体代码不做详解。

1. LeakCanary涉及类图关系解析

2. LeakCanary执行序列图解析

注:图片出自https://www.jianshu.com/p/0049e9b344b0

3. LeakCanary执行流程解析
/**
 *所属类:ExampleApplication.java
 */
protected void setupLeakCanary() {
    if (LeakCanary.isInAnalyzerProcess(this)) {
      // This process is dedicated to LeakCanary for heap analysis.
      // You should not init your app in this process.
      return;
    }
    enabledStrictMode();
    LeakCanary.install(this);
  }

安装LeakCanary前先判断当前进程是否是HeapAnalyzerService所在的远程分析进程,如果是分析进程就直接返回,否则调用LeakCanary的install()方法,该方法就是入口。

 /**
   * Creates a {@link RefWatcher} that works out of the box, and starts watching activity
   * references (on ICS+).
   * 所属类:LeakCanary.java
   */
  public static RefWatcher install(Application application) {
    return refWatcher(application).listenerServiceClass(DisplayLeakService.class)
        .excludedRefs(AndroidExcludedRefs.createAppDefaults().build())
        .buildAndInstall();
  }

创建一个RefWatcher,开始监听activity引用,注:如果需要监听fragment,需要手动进行监听。refWatcher(application)方法返回AndroidRefWatcherBuilder对象,listenerServiceClass(DisplayLeakService.class)对解析结果做回调监听此处为display service,excludedRefs(AndroidExcludedRefs.createAppDefaults().build())设置需要过滤的内存泄露,一般为已知的sdk内存泄露以及第三方库内存泄露。然后调用buildAndInstall()。

 /**
   * Creates a {@link RefWatcher} instance and starts watching activity references (on ICS+).
   * 所属类:AndroidRefWatcherBuilder.java
   */
  public RefWatcher buildAndInstall() {
    RefWatcher refWatcher = build();
    if (refWatcher != DISABLED) {
      LeakCanary.enableDisplayLeakActivity(context);
      ActivityRefWatcher.install((Application) context, refWatcher);
    }
    return refWatcher;
  }

builid调用父类方法创建RefWatcher, 然后调用ActivityRefWatcher.install((Application) context, refWatcher);开始监控activity。首先,看下父类build()方法:

/** 
 *Creates a {@link RefWatcher}.
 * 所属类:RefWatcherBuilder.java
 */
  public final RefWatcher build() {
    if (isDisabled()) {
      return RefWatcher.DISABLED;
    }

    ExcludedRefs excludedRefs = this.excludedRefs;
    if (excludedRefs == null) {
      excludedRefs = defaultExcludedRefs();
    }

    HeapDump.Listener heapDumpListener = this.heapDumpListener;
    if (heapDumpListener == null) {
      heapDumpListener = defaultHeapDumpListener();
    }

    DebuggerControl debuggerControl = this.debuggerControl;
    if (debuggerControl == null) {
      debuggerControl = defaultDebuggerControl();
    }

    HeapDumper heapDumper = this.heapDumper;
    if (heapDumper == null) {
      heapDumper = defaultHeapDumper();
    }

    WatchExecutor watchExecutor = this.watchExecutor;
    if (watchExecutor == null) {
      watchExecutor = defaultWatchExecutor();
    }

    GcTrigger gcTrigger = this.gcTrigger;
    if (gcTrigger == null) {
      gcTrigger = defaultGcTrigger();
    }

    return new RefWatcher(watchExecutor, debuggerControl, gcTrigger, heapDumper, heapDumpListener,
        excludedRefs);
  }

调用子类AndroidRefWatcherBuilder.java方法defaultHeapDumpListener(),创建ServiceHeapDumpListener赋值heapDumpListener(ServiceHeapDumpListener用于回调HeapAnalyzerService进行解析.hprof源文件),进行defaultHeapDumper()创建AndroidHeapDumper赋值heapDumper(AndroidHeapDumper用于dump .hprof源文件),初始化各个参数之后创建RefWatcher。回头看下ActivityRefWatcher.install((Application) context, refWatcher);

/** 
 * 所属类:ActivityRefWatcher.java
 */
public static void install(Application application, RefWatcher refWatcher) {
    new ActivityRefWatcher(application, refWatcher).watchActivities();
  }

开始监控activity,具体看下watchActivities()实现。

/** 
 * 所属类:ActivityRefWatcher.java
 */
public void watchActivities() {
    // Make sure you don't get installed twice.
    stopWatchingActivities();
    application.registerActivityLifecycleCallbacks(lifecycleCallbacks);
  }

注册application回调,具体看下lifecycleCallbacks,

/** 
 * 所属类:ActivityRefWatcher.java
 */
private final Application.ActivityLifecycleCallbacks lifecycleCallbacks =
      new Application.ActivityLifecycleCallbacks() {
        @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
        }

        @Override public void onActivityStarted(Activity activity) {
        }

        @Override public void onActivityResumed(Activity activity) {
        }

        @Override public void onActivityPaused(Activity activity) {
        }

        @Override public void onActivityStopped(Activity activity) {
        }

        @Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
        }

        @Override public void onActivityDestroyed(Activity activity) {
          ActivityRefWatcher.this.onActivityDestroyed(activity);
        }
      };

再看下ActivityRefWatcher.this.onActivityDestroyed(activity);具体实现,

/** 
 * 所属类:ActivityRefWatcher.java
 */
void onActivityDestroyed(Activity activity) {
    refWatcher.watch(activity);
  }

这里自动对activity做了监控,所以为什么我们不用手动监控activity,而要手动监控fragment的原因就是这个了。下面我们看下refWatcher是如何实现对引用对象进行监听判断是否是内存泄露的,跟进去看下具体实现代码。

/**
   * Watches the provided references and checks if it can be GCed. This method is non blocking,
   * the check is done on the {@link WatchExecutor} this {@link RefWatcher} has been constructed
   * with.
   *
   * @param referenceName An logical identifier for the watched object.
   *  所属类:RefWatcher.java
   */
  public void watch(Object watchedReference, String referenceName) {
    if (this == DISABLED) {
      return;
    }
    checkNotNull(watchedReference, "watchedReference");
    checkNotNull(referenceName, "referenceName");
    final long watchStartNanoTime = System.nanoTime();
    String key = UUID.randomUUID().toString();
    retainedKeys.add(key);
    final KeyedWeakReference reference =
        new KeyedWeakReference(watchedReference, key, referenceName, queue);

    ensureGoneAsync(watchStartNanoTime, reference);
  }

针对引用object创建对应的weak引用,关联queue队列,queue为ReferenceQueue,所有weak引用被回收都会进入queue,然后调用ensureGoneAsync方法,看下具体实现代码,

 /**
   *  所属类:RefWatcher.java
   */
@SuppressWarnings("ReferenceEquality") // Explicitly checking for named null.
  Retryable.Result ensureGone(final KeyedWeakReference reference, final long watchStartNanoTime) {
    long gcStartNanoTime = System.nanoTime();
    long watchDurationMs = NANOSECONDS.toMillis(gcStartNanoTime - watchStartNanoTime);

    //移除已回收的对象
    removeWeaklyReachableReferences();

    if (debuggerControl.isDebuggerAttached()) {
      // The debugger can create false leaks.
      return RETRY;
    }

    //判断对象是否被回收
    if (gone(reference)) {
      return DONE;
    }

    //手动GC
    gcTrigger.runGc();

    //移除已回收的对象
    removeWeaklyReachableReferences();

    if (!gone(reference)) {//如果没有被回收,dump原始信息
      long startDumpHeap = System.nanoTime();
      long gcDurationMs = NANOSECONDS.toMillis(startDumpHeap - gcStartNanoTime);

        File heapDumpFile = heapDumper.dumpHeap();
      if (heapDumpFile == RETRY_LATER) {
        // Could not dump the heap.
        return RETRY;
      }
      long heapDumpDurationMs = NANOSECONDS.toMillis(System.nanoTime() - startDumpHeap);
      heapdumpListener.analyze(
          new HeapDump(heapDumpFile, reference.key, reference.name, excludedRefs, watchDurationMs,
              gcDurationMs, heapDumpDurationMs));
    }
    return DONE;
  }

移除已回收的对象,判断对应的weak引用是否被回收,如果没有被回收手动触发GC,移除已回收的对象,如果weak引用还存在则dump对应的原始信息,回调解析,heapdumpListener就是之前ServiceHeapDumpListener,看下heapdumpListener.analyze()的具体实现,

 /**
   *  所属类:ServiceHeapDumpListener.java
   */
@Override public void analyze(HeapDump heapDump) {
    checkNotNull(heapDump, "heapDump");
    HeapAnalyzerService.runAnalysis(context, heapDump, listenerServiceClass);
  }

调用解析service,解析源文件,看下里面做了什么,

/**
   *  所属类:HeapAnalyzerService.java
   */
@Override protected void onHandleIntent(Intent intent) {
    if (intent == null) {
      CanaryLog.d("HeapAnalyzerService received a null intent, ignoring.");
      return;
    }
    String listenerClassName = intent.getStringExtra(LISTENER_CLASS_EXTRA);
    HeapDump heapDump = (HeapDump) intent.getSerializableExtra(HEAPDUMP_EXTRA);

    HeapAnalyzer heapAnalyzer = new HeapAnalyzer(heapDump.excludedRefs);

    AnalysisResult result = heapAnalyzer.checkForLeak(heapDump.heapDumpFile, heapDump.referenceKey);
    AbstractAnalysisResultService.sendResultToListener(this, listenerClassName, heapDump, result);
  }

调用HeapAnalyzer.checkForLeak()解析源文件,然后通过调用DisplayLeakService父类方法sendResultToListener启动DisplayLeakService,将解析内容通过onHeapAnalyzed(heapDump, result)发送给DisplayLeakService,看下具体实现.

/**
   *  所属类:DisplayLeakService.java
   */
@Override protected final void onHeapAnalyzed(HeapDump heapDump, AnalysisResult result) {
    String leakInfo = leakInfo(this, heapDump, result, true);
    CanaryLog.d("%s", leakInfo);

    boolean resultSaved = false;
    boolean shouldSaveResult = result.leakFound || result.failure != null;
    if (shouldSaveResult) {
      heapDump = renameHeapdump(heapDump);
      resultSaved = saveResult(heapDump, result);
    }

    PendingIntent pendingIntent;
    String contentTitle;
    String contentText;

    if (!shouldSaveResult) {
      contentTitle = getString(R.string.leak_canary_no_leak_title);
      contentText = getString(R.string.leak_canary_no_leak_text);
      pendingIntent = null;
    } else if (resultSaved) {
      pendingIntent = DisplayLeakActivity.createPendingIntent(this, heapDump.referenceKey);

      if (result.failure == null) {
        String size = formatShortFileSize(this, result.retainedHeapSize);
        String className = classSimpleName(result.className);
        if (result.excludedLeak) {
          contentTitle = getString(R.string.leak_canary_leak_excluded, className, size);
        } else {
          contentTitle = getString(R.string.leak_canary_class_has_leaked, className, size);
        }
      } else {
        contentTitle = getString(R.string.leak_canary_analysis_failed);
      }
      contentText = getString(R.string.leak_canary_notification_message);
    } else {
      contentTitle = getString(R.string.leak_canary_could_not_save_title);
      contentText = getString(R.string.leak_canary_could_not_save_text);
      pendingIntent = null;
    }
    // New notification id every second.
    int notificationId = (int) (SystemClock.uptimeMillis() / 1000);
    showNotification(this, contentTitle, contentText, pendingIntent, notificationId);
    afterDefaultHandling(heapDump, result, leakInfo);
  }

生成display所需要的result文件,弹框提示内存泄露信息,至此了解了leakcanary从监控到解析再到展示泄露信息的一个全过程。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
pytorch-cnn-股票预测是一个使用PyTorch框架实现的卷积神经网络模型,用于预测股票价格走势的代码。 这个项目的目的是通过训练一个卷积神经网络模型,来预测股票价格的未来走势。卷积神经网络是一种深度学习模型,通过自动提取特征并学习数据之间的非线性关系来进行预测。 在这个码中,首先进行数据的预处理。通常会使用历史股票价格的时间序列作为输入数据,以及对应的目标值作为标签。数据预处理的操作可能包括数据标准化、缺失值填充等等。 接下来,我们构建卷积神经网络模型。在码中,可能会使用PyTorch提供的卷积层(Convolutional Layer)、池化层(Pooling Layer)和全连接层(Fully Connected Layer)等组件来构建模型,以及使用ReLU、Dropout等激活函数和正则化方法来提高模型的性能。 然后,我们定义损失函数,通常选择均方误差(Mean Squared Error)或交叉熵损失(Cross Entropy Loss)作为模型训练的目标函数,以便优化模型的预测结果。 最后,我们使用训练数据来训练模型,并使用测试数据来评估模型的性能。在码中,我们会定义训练函数和测试函数,通过迭代训练,不断调整模型参数,以使得模型能够更准确地预测未知数据的输出结果。 总结来说,pytorch-cnn-股票预测-码是一个基于PyTorch框架实现的卷积神经网络模型,用于预测股票价格走势的代码。通过数据预处理、构建网络模型、定义损失函数和训练评估等步骤,可以使用这个代码来进行股票预测模型的训练和测试。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值