| |
| <!doctype html> |
| <html lang="en" class="no-js"> |
| <head> |
| |
| <meta charset="utf-8"> |
| <meta name="viewport" content="width=device-width,initial-scale=1"> |
| |
| <meta name="description" content="A memory leak detection library for Android"> |
| |
| |
| <meta name="author" content="Square, Inc."> |
| |
| |
| <link rel="canonical" href="https://square.github.io/leakcanary/changelog/"> |
| |
| |
| <link rel="prev" href="../api/leakcanary/"> |
| |
| |
| <link rel="icon" href="../images/logo.png"> |
| <meta name="generator" content="mkdocs-1.4.2, mkdocs-material-9.1.3"> |
| |
| |
| |
| <title>Change Log - LeakCanary</title> |
| |
| |
| |
| <link rel="stylesheet" href="../assets/stylesheets/main.c4a75a56.min.css"> |
| |
| |
| <link rel="stylesheet" href="../assets/stylesheets/palette.a0c5b2b5.min.css"> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> |
| <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,700,700i%7CRoboto+Mono:400,400i,700,700i&display=fallback"> |
| <style>:root{--md-text-font:"Roboto";--md-code-font:"Roboto Mono"}</style> |
| |
| |
| |
| <script>__md_scope=new URL("..",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script> |
| |
| |
| |
| |
| |
| |
| </head> |
| |
| |
| |
| |
| |
| |
| |
| <body dir="ltr" data-md-color-scheme="default" data-md-color-primary="deep-orange" data-md-color-accent="deep-purple"> |
| |
| |
| |
| <input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off"> |
| <input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off"> |
| <label class="md-overlay" for="__drawer"></label> |
| <div data-md-component="skip"> |
| |
| |
| <a href="#change-log" class="md-skip"> |
| Skip to content |
| </a> |
| |
| </div> |
| <div data-md-component="announce"> |
| |
| <aside class="md-banner"> |
| <div class="md-banner__inner md-grid md-typeset"> |
| |
| |
| Upgrade to <a href="../changelog/">LeakCanary <strong>2.14</strong></a> 🐤 Want to help? <a href="../how_to_help/">Here's how you can contribute<a> 🙏 |
| |
| </div> |
| |
| </aside> |
| |
| </div> |
| |
| |
| |
| |
| |
| |
| <header class="md-header md-header--shadow" data-md-component="header"> |
| <nav class="md-header__inner md-grid" aria-label="Header"> |
| <a href=".." title="LeakCanary" class="md-header__button md-logo" aria-label="LeakCanary" data-md-component="logo"> |
| |
| <img src="../images/logo.png" alt="logo"> |
| |
| </a> |
| <label class="md-header__button md-icon" for="__drawer"> |
| <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"/></svg> |
| </label> |
| <div class="md-header__title" data-md-component="header-title"> |
| <div class="md-header__ellipsis"> |
| <div class="md-header__topic"> |
| <span class="md-ellipsis"> |
| LeakCanary |
| </span> |
| </div> |
| <div class="md-header__topic" data-md-component="header-topic"> |
| <span class="md-ellipsis"> |
| |
| Change Log |
| |
| </span> |
| </div> |
| </div> |
| </div> |
| |
| |
| |
| <label class="md-header__button md-icon" for="__search"> |
| <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"/></svg> |
| </label> |
| <div class="md-search" data-md-component="search" role="dialog"> |
| <label class="md-search__overlay" for="__search"></label> |
| <div class="md-search__inner" role="search"> |
| <form class="md-search__form" name="search"> |
| <input type="text" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required> |
| <label class="md-search__icon md-icon" for="__search"> |
| <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"/></svg> |
| <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"/></svg> |
| </label> |
| <nav class="md-search__options" aria-label="Search"> |
| |
| <button type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1"> |
| <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41Z"/></svg> |
| </button> |
| </nav> |
| |
| </form> |
| <div class="md-search__output"> |
| <div class="md-search__scrollwrap" data-md-scrollfix> |
| <div class="md-search-result" data-md-component="search-result"> |
| <div class="md-search-result__meta"> |
| Initializing search |
| </div> |
| <ol class="md-search-result__list" role="presentation"></ol> |
| </div> |
| </div> |
| </div> |
| </div> |
| </div> |
| |
| |
| <div class="md-header__source"> |
| <a href="https://github.com/square/leakcanary" title="Go to repository" class="md-source" data-md-component="source"> |
| <div class="md-source__icon md-icon"> |
| |
| <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><!--! Font Awesome Free 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg> |
| </div> |
| <div class="md-source__repository"> |
| LeakCanary |
| </div> |
| </a> |
| </div> |
| |
| </nav> |
| |
| </header> |
| |
| <div class="md-container" data-md-component="container"> |
| |
| |
| |
| |
| |
| |
| <main class="md-main" data-md-component="main"> |
| <div class="md-main__inner md-grid"> |
| |
| |
| |
| <div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" > |
| <div class="md-sidebar__scrollwrap"> |
| <div class="md-sidebar__inner"> |
| |
| |
| |
| <nav class="md-nav md-nav--primary" aria-label="Navigation" data-md-level="0"> |
| <label class="md-nav__title" for="__drawer"> |
| <a href=".." title="LeakCanary" class="md-nav__button md-logo" aria-label="LeakCanary" data-md-component="logo"> |
| |
| <img src="../images/logo.png" alt="logo"> |
| |
| </a> |
| LeakCanary |
| </label> |
| |
| <div class="md-nav__source"> |
| <a href="https://github.com/square/leakcanary" title="Go to repository" class="md-source" data-md-component="source"> |
| <div class="md-source__icon md-icon"> |
| |
| <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><!--! Font Awesome Free 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg> |
| </div> |
| <div class="md-source__repository"> |
| LeakCanary |
| </div> |
| </a> |
| </div> |
| |
| <ul class="md-nav__list" data-md-scrollfix> |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class="md-nav__item"> |
| <a href=".." class="md-nav__link"> |
| Overview |
| </a> |
| </li> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class="md-nav__item"> |
| <a href="../getting_started/" class="md-nav__link"> |
| Getting Started |
| </a> |
| </li> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class="md-nav__item md-nav__item--nested"> |
| |
| |
| |
| |
| <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" > |
| |
| |
| |
| <label class="md-nav__link" for="__nav_3" id="__nav_3_label" tabindex="0"> |
| Fundamentals |
| <span class="md-nav__icon md-icon"></span> |
| </label> |
| |
| <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="false"> |
| <label class="md-nav__title" for="__nav_3"> |
| <span class="md-nav__icon md-icon"></span> |
| Fundamentals |
| </label> |
| <ul class="md-nav__list" data-md-scrollfix> |
| |
| |
| |
| |
| |
| |
| <li class="md-nav__item"> |
| <a href="../fundamentals/" class="md-nav__link"> |
| Introduction |
| </a> |
| </li> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class="md-nav__item"> |
| <a href="../fundamentals-how-leakcanary-works/" class="md-nav__link"> |
| How LeakCanary works |
| </a> |
| </li> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class="md-nav__item"> |
| <a href="../fundamentals-fixing-a-memory-leak/" class="md-nav__link"> |
| Fixing a memory leak |
| </a> |
| </li> |
| |
| |
| |
| |
| </ul> |
| </nav> |
| </li> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class="md-nav__item md-nav__item--nested"> |
| |
| |
| |
| |
| <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_4" > |
| |
| |
| |
| <label class="md-nav__link" for="__nav_4" id="__nav_4_label" tabindex="0"> |
| LeakCanary at scale |
| <span class="md-nav__icon md-icon"></span> |
| </label> |
| |
| <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_4_label" aria-expanded="false"> |
| <label class="md-nav__title" for="__nav_4"> |
| <span class="md-nav__icon md-icon"></span> |
| LeakCanary at scale |
| </label> |
| <ul class="md-nav__list" data-md-scrollfix> |
| |
| |
| |
| |
| |
| |
| <li class="md-nav__item"> |
| <a href="../ui-tests/" class="md-nav__link"> |
| Leak detection in UI tests |
| </a> |
| </li> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class="md-nav__item"> |
| <a href="../uploading/" class="md-nav__link"> |
| Uploading analysis results |
| </a> |
| </li> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class="md-nav__item"> |
| <a href="../leakcanary-for-releases/" class="md-nav__link"> |
| LeakCanary for releases |
| </a> |
| </li> |
| |
| |
| |
| |
| </ul> |
| </nav> |
| </li> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class="md-nav__item md-nav__item--nested"> |
| |
| |
| |
| |
| <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" > |
| |
| |
| |
| <label class="md-nav__link" for="__nav_5" id="__nav_5_label" tabindex="0"> |
| Help & Community |
| <span class="md-nav__icon md-icon"></span> |
| </label> |
| |
| <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="false"> |
| <label class="md-nav__title" for="__nav_5"> |
| <span class="md-nav__icon md-icon"></span> |
| Help & Community |
| </label> |
| <ul class="md-nav__list" data-md-scrollfix> |
| |
| |
| |
| |
| |
| |
| <li class="md-nav__item"> |
| <a href="../recipes/" class="md-nav__link"> |
| Code recipes |
| </a> |
| </li> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class="md-nav__item"> |
| <a href="../faq/" class="md-nav__link"> |
| FAQ |
| </a> |
| </li> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class="md-nav__item"> |
| <a href="../support/" class="md-nav__link"> |
| Support |
| </a> |
| </li> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class="md-nav__item"> |
| <a href="../upgrading-to-leakcanary-2.0/" class="md-nav__link"> |
| Upgrading to LeakCanary 2 |
| </a> |
| </li> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class="md-nav__item"> |
| <a href="../recorded-presentations/" class="md-nav__link"> |
| Recorded Presentations |
| </a> |
| </li> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class="md-nav__item"> |
| <a href="../blog-articles/" class="md-nav__link"> |
| Blog Articles |
| </a> |
| </li> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class="md-nav__item"> |
| <a href="https://stackoverflow.com/questions/tagged/leakcanary?sort=active" class="md-nav__link"> |
| Stack Overflow ⏏ |
| </a> |
| </li> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class="md-nav__item md-nav__item--nested"> |
| |
| |
| |
| |
| <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5_8" > |
| |
| |
| |
| <label class="md-nav__link" for="__nav_5_8" id="__nav_5_8_label" tabindex="0"> |
| Contributing |
| <span class="md-nav__icon md-icon"></span> |
| </label> |
| |
| <nav class="md-nav" data-md-level="2" aria-labelledby="__nav_5_8_label" aria-expanded="false"> |
| <label class="md-nav__title" for="__nav_5_8"> |
| <span class="md-nav__icon md-icon"></span> |
| Contributing |
| </label> |
| <ul class="md-nav__list" data-md-scrollfix> |
| |
| |
| |
| |
| |
| |
| <li class="md-nav__item"> |
| <a href="../code_of_conduct/" class="md-nav__link"> |
| Code of Conduct |
| </a> |
| </li> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class="md-nav__item"> |
| <a href="../dev-env/" class="md-nav__link"> |
| Dev Environment |
| </a> |
| </li> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class="md-nav__item"> |
| <a href="../releasing/" class="md-nav__link"> |
| Releasing |
| </a> |
| </li> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class="md-nav__item"> |
| <a href="../how_to_help/" class="md-nav__link"> |
| How to help |
| </a> |
| </li> |
| |
| |
| |
| |
| </ul> |
| </nav> |
| </li> |
| |
| |
| |
| |
| </ul> |
| </nav> |
| </li> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class="md-nav__item md-nav__item--nested"> |
| |
| |
| |
| |
| <input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_6" > |
| |
| |
| |
| <label class="md-nav__link" for="__nav_6" id="__nav_6_label" tabindex="0"> |
| Shark |
| <span class="md-nav__icon md-icon"></span> |
| </label> |
| |
| <nav class="md-nav" data-md-level="1" aria-labelledby="__nav_6_label" aria-expanded="false"> |
| <label class="md-nav__title" for="__nav_6"> |
| <span class="md-nav__icon md-icon"></span> |
| Shark |
| </label> |
| <ul class="md-nav__list" data-md-scrollfix> |
| |
| |
| |
| |
| |
| |
| <li class="md-nav__item"> |
| <a href="../shark/" class="md-nav__link"> |
| Overview |
| </a> |
| </li> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class="md-nav__item"> |
| <a href="../api/shark/" class="md-nav__link"> |
| Shark API |
| </a> |
| </li> |
| |
| |
| |
| |
| </ul> |
| </nav> |
| </li> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class="md-nav__item"> |
| <a href="../api/leakcanary/" class="md-nav__link"> |
| LeakCanary API |
| </a> |
| </li> |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| <li class="md-nav__item md-nav__item--active"> |
| |
| <input class="md-nav__toggle md-toggle" type="checkbox" id="__toc"> |
| |
| |
| |
| |
| |
| <label class="md-nav__link md-nav__link--active" for="__toc"> |
| Change Log |
| <span class="md-nav__icon md-icon"></span> |
| </label> |
| |
| <a href="./" class="md-nav__link md-nav__link--active"> |
| Change Log |
| </a> |
| |
| |
| |
| <nav class="md-nav md-nav--secondary" aria-label="Table of contents"> |
| |
| |
| |
| |
| |
| |
| <label class="md-nav__title" for="__toc"> |
| <span class="md-nav__icon md-icon"></span> |
| Table of contents |
| </label> |
| <ul class="md-nav__list" data-md-component="toc" data-md-scrollfix> |
| |
| <li class="md-nav__item"> |
| <a href="#version-30-alpha-8-2024-06-04" class="md-nav__link"> |
| Version 3.0 Alpha 8 (2024-06-04) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-30-alpha-7-2024-05-30" class="md-nav__link"> |
| Version 3.0 Alpha 7 (2024-05-30) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 3.0 Alpha 7 (2024-05-30)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#heap-growth-espresso-test-example" class="md-nav__link"> |
| Heap Growth: Espresso test example |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#heap-growth-jvm-junit-test-example" class="md-nav__link"> |
| Heap Growth: JVM Junit test example. |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#heap-growth-ui-automator-test-example" class="md-nav__link"> |
| Heap Growth: UI Automator test example. |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#heap-growth-shark-cli" class="md-nav__link"> |
| Heap Growth: Shark CLI |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-30-alpha-6-2024-05-21" class="md-nav__link"> |
| Version 3.0 Alpha 6 (2024-05-21) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 3.0 Alpha 6 (2024-05-21)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#heap-growth" class="md-nav__link"> |
| Heap Growth |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-30-alpha-4-2024-05-10" class="md-nav__link"> |
| Version 3.0 Alpha 4 (2024-05-10) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 3.0 Alpha 4 (2024-05-10)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#heap-growth-espresso-test-example_1" class="md-nav__link"> |
| Heap Growth: Espresso test example |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#heap-growth-ui-automator-test-example_1" class="md-nav__link"> |
| Heap Growth: UI Automator test example. |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#heap-growth-shark-cli_1" class="md-nav__link"> |
| Heap Growth: Shark CLI |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-214-2024-04-17" class="md-nav__link"> |
| Version 2.14 (2024-04-17) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-30-alpha-1-2024-01-09" class="md-nav__link"> |
| Version 3.0 Alpha 1 (2024-01-09) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 3.0 Alpha 1 (2024-01-09)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#heap-growth_1" class="md-nav__link"> |
| Heap Growth |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#reference-readers" class="md-nav__link"> |
| Reference readers |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#objectwatcher-apis-refactor" class="md-nav__link"> |
| ObjectWatcher APIs refactor |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#other-bug-fixes-and-improvements" class="md-nav__link"> |
| Other bug fixes and improvements 🐛🔨 |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-213-2024-01-03" class="md-nav__link"> |
| Version 2.13 (2024-01-03) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-212-2023-06-29" class="md-nav__link"> |
| Version 2.12 (2023-06-29) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-211-2023-05-17" class="md-nav__link"> |
| Version 2.11 (2023-05-17) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-210-2022-11-10" class="md-nav__link"> |
| Version 2.10 (2022-11-10) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 2.10 (2022-11-10)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#experimental-neo4j-heap-dump-exploration" class="md-nav__link"> |
| Experimental Neo4j heap dump exploration |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#other-bug-fixes-and-improvements_1" class="md-nav__link"> |
| Other bug fixes and improvements 🐛🔨 |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-291-2022-04-20" class="md-nav__link"> |
| Version 2.9.1 (2022-04-20) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 2.9.1 (2022-04-20)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#preface" class="md-nav__link"> |
| Preface |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#new-metrics-in-heap-analysis-metadata" class="md-nav__link"> |
| New metrics in heap analysis metadata |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#performance-improvements" class="md-nav__link"> |
| Performance improvements |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#breaking-change-failtestonleakrunlistener-deleted" class="md-nav__link"> |
| Breaking change: FailTestOnLeakRunListener deleted |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#other-bug-fixes-and-improvements_2" class="md-nav__link"> |
| Other bug fixes and improvements 🐛🔨 |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-281-2022-01-06" class="md-nav__link"> |
| Version 2.8.1 (2022-01-06) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 2.8.1 (2022-01-06)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#thanks" class="md-nav__link"> |
| Thanks |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#crash-fixes" class="md-nav__link"> |
| Crash fixes 💥💥💥 |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-28-2022-01-04" class="md-nav__link"> |
| Version 2.8 (2022-01-04) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 2.8 (2022-01-04)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#preface_1" class="md-nav__link"> |
| Preface |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#thanks_1" class="md-nav__link"> |
| Thanks |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#improved-support-for-data-structure-internals" class="md-nav__link"> |
| Improved support for data structure internals |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#objectanimator-leaks" class="md-nav__link"> |
| ObjectAnimator leaks |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#leak-detection-in-tests" class="md-nav__link"> |
| Leak detection in tests |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#android-12" class="md-nav__link"> |
| Android 12 |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#workmanager" class="md-nav__link"> |
| WorkManager |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#multi-process" class="md-nav__link"> |
| Multi process |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#androidx-app-startup" class="md-nav__link"> |
| AndroidX App Startup |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#event-listeners" class="md-nav__link"> |
| Event listeners |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#other-bug-fixes-and-improvements_3" class="md-nav__link"> |
| Other bug fixes and improvements 🐛🔨 |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-27-2021-03-26" class="md-nav__link"> |
| Version 2.7 (2021-03-26) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 2.7 (2021-03-26)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#finer-grained-root-view-watching" class="md-nav__link"> |
| Finer grained root view watching |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#targeting-android-12" class="md-nav__link"> |
| Targeting Android 12 |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#bug-fixes-and-improvements" class="md-nav__link"> |
| Bug fixes and improvements 🐛🔨 |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-26-christmas-release-2020-12-24" class="md-nav__link"> |
| Version 2.6 - Christmas Release 🎄 (2020-12-24) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 2.6 - Christmas Release 🎄 (2020-12-24)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#detecting-root-views-retained-after-viewondetachedfromwindow" class="md-nav__link"> |
| Detecting root views retained after View.onDetachedFromWindow() |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#detecting-services-retained-after-serviceondestroy" class="md-nav__link"> |
| Detecting services retained after Service.onDestroy() |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#configuring-retained-object-detection" class="md-nav__link"> |
| Configuring retained object detection |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#dumping-the-heap-on-screen-off" class="md-nav__link"> |
| Dumping the heap on screen off |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#leakcanary-for-releases" class="md-nav__link"> |
| LeakCanary for releases |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#more-leak-fixes-in-plumber" class="md-nav__link"> |
| More leak fixes in Plumber |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#bug-fixes-and-improvements_1" class="md-nav__link"> |
| Bug fixes and improvements 🐛🔨 |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-25-2020-10-01" class="md-nav__link"> |
| Version 2.5 (2020-10-01) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 2.5 (2020-10-01)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#heap-analysis-is-twice-as-fast" class="md-nav__link"> |
| Heap analysis is twice as fast 🐤💨 |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#compute-retained-size-within-the-leak-trace" class="md-nav__link"> |
| Compute retained size within the leak trace |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#disable-leakcanary-from-the-ui" class="md-nav__link"> |
| Disable LeakCanary from the UI |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#deobfuscating-hprof-files" class="md-nav__link"> |
| Deobfuscating hprof files |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#bug-fixes-and-improvements_2" class="md-nav__link"> |
| Bug fixes and improvements 🐛🔨 |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-24-2020-06-10" class="md-nav__link"> |
| Version 2.4 (2020-06-10) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 2.4 (2020-06-10)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#plumber-android-is-a-new-artifact-that-fixes-known-android-leaks" class="md-nav__link"> |
| plumber-android is a new artifact that fixes known Android leaks 🚽🔧 |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#analyzing-leaks-from-the-cli-is-easier-than-ever" class="md-nav__link"> |
| Analyzing leaks from the CLI is easier than ever 🍺 |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#support-for-android-test-orchestrator" class="md-nav__link"> |
| Support for Android Test Orchestrator 🎼 |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#no-more-master-branch" class="md-nav__link"> |
| No more master branch |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#bug-fixes-and-improvements_3" class="md-nav__link"> |
| Bug fixes and improvements 🐛🔨 |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-23-2020-04-08" class="md-nav__link"> |
| Version 2.3 (2020-04-08) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 2.3 (2020-04-08)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#leakcanary-will-now-crash-in-release-builds" class="md-nav__link"> |
| LeakCanary will now crash in release builds |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#doc-site" class="md-nav__link"> |
| Doc site 🛀💥 |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#bug-fixes-and-improvements_4" class="md-nav__link"> |
| Bug fixes and improvements 😉 |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-22-2020-02-05" class="md-nav__link"> |
| Version 2.2 (2020-02-05) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 2.2 (2020-02-05)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#viewmodel-leak-detection" class="md-nav__link"> |
| ViewModel leak detection |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#android-tv" class="md-nav__link"> |
| Android TV |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#java-friendly-config-builders" class="md-nav__link"> |
| Java-friendly Config builders |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-21-2019-12-31" class="md-nav__link"> |
| Version 2.1 (2019-12-31) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 2.1 (2019-12-31)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#a-gradle-plugin-for-obfuscated-apps" class="md-nav__link"> |
| A Gradle plugin for obfuscated apps |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#ui-twix-tweaks" class="md-nav__link"> |
| UI twix tweaks |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#documentation-goodies" class="md-nav__link"> |
| Documentation goodies |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#api-breaking-bettering-changes" class="md-nav__link"> |
| API breaking bettering changes |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#interactive-cli" class="md-nav__link"> |
| Interactive CLI |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-20-2019-11-27" class="md-nav__link"> |
| Version 2.0 (2019-11-27) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 2.0 (2019-11-27)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#should-i-upgrade" class="md-nav__link"> |
| Should I upgrade? |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#so-whats-changed-since-163" class="md-nav__link"> |
| So, what's changed since 1.6.3? |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#random-facts" class="md-nav__link"> |
| Random facts |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#changes-since-20-beta-5" class="md-nav__link"> |
| Changes since 2.0 Beta 5 |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-20-beta-5-2019-11-25" class="md-nav__link"> |
| Version 2.0 Beta 5 (2019-11-25) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-20-beta-4-2019-11-18" class="md-nav__link"> |
| Version 2.0 Beta 4 (2019-11-18) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-20-beta-3-2019-08-22" class="md-nav__link"> |
| Version 2.0 Beta 3 (2019-08-22) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-20-beta-2-2019-08-02" class="md-nav__link"> |
| Version 2.0 Beta 2 (2019-08-02) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-20-beta-1-2019-07-30" class="md-nav__link"> |
| Version 2.0 Beta 1 (2019-07-30) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-20-alpha-3-2019-07-04" class="md-nav__link"> |
| Version 2.0 Alpha 3 (2019-07-04) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-20-alpha-2-2019-05-21" class="md-nav__link"> |
| Version 2.0 Alpha 2 (2019-05-21) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-20-alpha-1-2019-04-23" class="md-nav__link"> |
| Version 2.0 Alpha 1 (2019-04-23) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-163-2019-01-10" class="md-nav__link"> |
| Version 1.6.3 (2019-01-10) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-162-2018-10-16" class="md-nav__link"> |
| Version 1.6.2 (2018-10-16) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 1.6.2 (2018-10-16)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#public-api-changes" class="md-nav__link"> |
| Public API changes |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-161-2018-06-21" class="md-nav__link"> |
| Version 1.6.1 (2018-06-21) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 1.6.1 (2018-06-21)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#public-api-changes_1" class="md-nav__link"> |
| Public API changes |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-154-2017-09-22" class="md-nav__link"> |
| Version 1.5.4 (2017-09-22) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-153-2017-09-17" class="md-nav__link"> |
| Version 1.5.3 (2017-09-17) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-152-2017-08-09" class="md-nav__link"> |
| Version 1.5.2 (2017-08-09) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-151-2017-04-25" class="md-nav__link"> |
| Version 1.5.1 (2017-04-25) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-15-2016-09-28" class="md-nav__link"> |
| Version 1.5 (2016-09-28) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 1.5 (2016-09-28)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#public-api-changes_2" class="md-nav__link"> |
| Public API changes |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-14-2016-09-11" class="md-nav__link"> |
| Version 1.4 (2016-09-11) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-14-beta2-2016-03-23" class="md-nav__link"> |
| Version 1.4-beta2 (2016-03-23) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-14-beta1-2016-01-08" class="md-nav__link"> |
| Version 1.4-beta1 (2016-01-08) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 1.4-beta1 (2016-01-08)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#public-api-changes_3" class="md-nav__link"> |
| Public API changes |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-131-2015-05-16" class="md-nav__link"> |
| Version 1.3.1 (2015-05-16) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 1.3.1 (2015-05-16)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#public-api-changes_4" class="md-nav__link"> |
| Public API changes |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-13-2015-05-08" class="md-nav__link"> |
| Version 1.3 (2015-05-08) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 1.3 (2015-05-08)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#dependencies" class="md-nav__link"> |
| Dependencies |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| </ul> |
| |
| </nav> |
| |
| </li> |
| |
| |
| |
| </ul> |
| </nav> |
| </div> |
| </div> |
| </div> |
| |
| |
| |
| <div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" > |
| <div class="md-sidebar__scrollwrap"> |
| <div class="md-sidebar__inner"> |
| |
| |
| <nav class="md-nav md-nav--secondary" aria-label="Table of contents"> |
| |
| |
| |
| |
| |
| |
| <label class="md-nav__title" for="__toc"> |
| <span class="md-nav__icon md-icon"></span> |
| Table of contents |
| </label> |
| <ul class="md-nav__list" data-md-component="toc" data-md-scrollfix> |
| |
| <li class="md-nav__item"> |
| <a href="#version-30-alpha-8-2024-06-04" class="md-nav__link"> |
| Version 3.0 Alpha 8 (2024-06-04) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-30-alpha-7-2024-05-30" class="md-nav__link"> |
| Version 3.0 Alpha 7 (2024-05-30) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 3.0 Alpha 7 (2024-05-30)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#heap-growth-espresso-test-example" class="md-nav__link"> |
| Heap Growth: Espresso test example |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#heap-growth-jvm-junit-test-example" class="md-nav__link"> |
| Heap Growth: JVM Junit test example. |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#heap-growth-ui-automator-test-example" class="md-nav__link"> |
| Heap Growth: UI Automator test example. |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#heap-growth-shark-cli" class="md-nav__link"> |
| Heap Growth: Shark CLI |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-30-alpha-6-2024-05-21" class="md-nav__link"> |
| Version 3.0 Alpha 6 (2024-05-21) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 3.0 Alpha 6 (2024-05-21)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#heap-growth" class="md-nav__link"> |
| Heap Growth |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-30-alpha-4-2024-05-10" class="md-nav__link"> |
| Version 3.0 Alpha 4 (2024-05-10) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 3.0 Alpha 4 (2024-05-10)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#heap-growth-espresso-test-example_1" class="md-nav__link"> |
| Heap Growth: Espresso test example |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#heap-growth-ui-automator-test-example_1" class="md-nav__link"> |
| Heap Growth: UI Automator test example. |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#heap-growth-shark-cli_1" class="md-nav__link"> |
| Heap Growth: Shark CLI |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-214-2024-04-17" class="md-nav__link"> |
| Version 2.14 (2024-04-17) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-30-alpha-1-2024-01-09" class="md-nav__link"> |
| Version 3.0 Alpha 1 (2024-01-09) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 3.0 Alpha 1 (2024-01-09)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#heap-growth_1" class="md-nav__link"> |
| Heap Growth |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#reference-readers" class="md-nav__link"> |
| Reference readers |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#objectwatcher-apis-refactor" class="md-nav__link"> |
| ObjectWatcher APIs refactor |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#other-bug-fixes-and-improvements" class="md-nav__link"> |
| Other bug fixes and improvements 🐛🔨 |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-213-2024-01-03" class="md-nav__link"> |
| Version 2.13 (2024-01-03) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-212-2023-06-29" class="md-nav__link"> |
| Version 2.12 (2023-06-29) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-211-2023-05-17" class="md-nav__link"> |
| Version 2.11 (2023-05-17) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-210-2022-11-10" class="md-nav__link"> |
| Version 2.10 (2022-11-10) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 2.10 (2022-11-10)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#experimental-neo4j-heap-dump-exploration" class="md-nav__link"> |
| Experimental Neo4j heap dump exploration |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#other-bug-fixes-and-improvements_1" class="md-nav__link"> |
| Other bug fixes and improvements 🐛🔨 |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-291-2022-04-20" class="md-nav__link"> |
| Version 2.9.1 (2022-04-20) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 2.9.1 (2022-04-20)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#preface" class="md-nav__link"> |
| Preface |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#new-metrics-in-heap-analysis-metadata" class="md-nav__link"> |
| New metrics in heap analysis metadata |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#performance-improvements" class="md-nav__link"> |
| Performance improvements |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#breaking-change-failtestonleakrunlistener-deleted" class="md-nav__link"> |
| Breaking change: FailTestOnLeakRunListener deleted |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#other-bug-fixes-and-improvements_2" class="md-nav__link"> |
| Other bug fixes and improvements 🐛🔨 |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-281-2022-01-06" class="md-nav__link"> |
| Version 2.8.1 (2022-01-06) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 2.8.1 (2022-01-06)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#thanks" class="md-nav__link"> |
| Thanks |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#crash-fixes" class="md-nav__link"> |
| Crash fixes 💥💥💥 |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-28-2022-01-04" class="md-nav__link"> |
| Version 2.8 (2022-01-04) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 2.8 (2022-01-04)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#preface_1" class="md-nav__link"> |
| Preface |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#thanks_1" class="md-nav__link"> |
| Thanks |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#improved-support-for-data-structure-internals" class="md-nav__link"> |
| Improved support for data structure internals |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#objectanimator-leaks" class="md-nav__link"> |
| ObjectAnimator leaks |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#leak-detection-in-tests" class="md-nav__link"> |
| Leak detection in tests |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#android-12" class="md-nav__link"> |
| Android 12 |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#workmanager" class="md-nav__link"> |
| WorkManager |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#multi-process" class="md-nav__link"> |
| Multi process |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#androidx-app-startup" class="md-nav__link"> |
| AndroidX App Startup |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#event-listeners" class="md-nav__link"> |
| Event listeners |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#other-bug-fixes-and-improvements_3" class="md-nav__link"> |
| Other bug fixes and improvements 🐛🔨 |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-27-2021-03-26" class="md-nav__link"> |
| Version 2.7 (2021-03-26) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 2.7 (2021-03-26)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#finer-grained-root-view-watching" class="md-nav__link"> |
| Finer grained root view watching |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#targeting-android-12" class="md-nav__link"> |
| Targeting Android 12 |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#bug-fixes-and-improvements" class="md-nav__link"> |
| Bug fixes and improvements 🐛🔨 |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-26-christmas-release-2020-12-24" class="md-nav__link"> |
| Version 2.6 - Christmas Release 🎄 (2020-12-24) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 2.6 - Christmas Release 🎄 (2020-12-24)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#detecting-root-views-retained-after-viewondetachedfromwindow" class="md-nav__link"> |
| Detecting root views retained after View.onDetachedFromWindow() |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#detecting-services-retained-after-serviceondestroy" class="md-nav__link"> |
| Detecting services retained after Service.onDestroy() |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#configuring-retained-object-detection" class="md-nav__link"> |
| Configuring retained object detection |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#dumping-the-heap-on-screen-off" class="md-nav__link"> |
| Dumping the heap on screen off |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#leakcanary-for-releases" class="md-nav__link"> |
| LeakCanary for releases |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#more-leak-fixes-in-plumber" class="md-nav__link"> |
| More leak fixes in Plumber |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#bug-fixes-and-improvements_1" class="md-nav__link"> |
| Bug fixes and improvements 🐛🔨 |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-25-2020-10-01" class="md-nav__link"> |
| Version 2.5 (2020-10-01) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 2.5 (2020-10-01)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#heap-analysis-is-twice-as-fast" class="md-nav__link"> |
| Heap analysis is twice as fast 🐤💨 |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#compute-retained-size-within-the-leak-trace" class="md-nav__link"> |
| Compute retained size within the leak trace |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#disable-leakcanary-from-the-ui" class="md-nav__link"> |
| Disable LeakCanary from the UI |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#deobfuscating-hprof-files" class="md-nav__link"> |
| Deobfuscating hprof files |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#bug-fixes-and-improvements_2" class="md-nav__link"> |
| Bug fixes and improvements 🐛🔨 |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-24-2020-06-10" class="md-nav__link"> |
| Version 2.4 (2020-06-10) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 2.4 (2020-06-10)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#plumber-android-is-a-new-artifact-that-fixes-known-android-leaks" class="md-nav__link"> |
| plumber-android is a new artifact that fixes known Android leaks 🚽🔧 |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#analyzing-leaks-from-the-cli-is-easier-than-ever" class="md-nav__link"> |
| Analyzing leaks from the CLI is easier than ever 🍺 |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#support-for-android-test-orchestrator" class="md-nav__link"> |
| Support for Android Test Orchestrator 🎼 |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#no-more-master-branch" class="md-nav__link"> |
| No more master branch |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#bug-fixes-and-improvements_3" class="md-nav__link"> |
| Bug fixes and improvements 🐛🔨 |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-23-2020-04-08" class="md-nav__link"> |
| Version 2.3 (2020-04-08) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 2.3 (2020-04-08)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#leakcanary-will-now-crash-in-release-builds" class="md-nav__link"> |
| LeakCanary will now crash in release builds |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#doc-site" class="md-nav__link"> |
| Doc site 🛀💥 |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#bug-fixes-and-improvements_4" class="md-nav__link"> |
| Bug fixes and improvements 😉 |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-22-2020-02-05" class="md-nav__link"> |
| Version 2.2 (2020-02-05) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 2.2 (2020-02-05)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#viewmodel-leak-detection" class="md-nav__link"> |
| ViewModel leak detection |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#android-tv" class="md-nav__link"> |
| Android TV |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#java-friendly-config-builders" class="md-nav__link"> |
| Java-friendly Config builders |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-21-2019-12-31" class="md-nav__link"> |
| Version 2.1 (2019-12-31) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 2.1 (2019-12-31)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#a-gradle-plugin-for-obfuscated-apps" class="md-nav__link"> |
| A Gradle plugin for obfuscated apps |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#ui-twix-tweaks" class="md-nav__link"> |
| UI twix tweaks |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#documentation-goodies" class="md-nav__link"> |
| Documentation goodies |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#api-breaking-bettering-changes" class="md-nav__link"> |
| API breaking bettering changes |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#interactive-cli" class="md-nav__link"> |
| Interactive CLI |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-20-2019-11-27" class="md-nav__link"> |
| Version 2.0 (2019-11-27) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 2.0 (2019-11-27)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#should-i-upgrade" class="md-nav__link"> |
| Should I upgrade? |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#so-whats-changed-since-163" class="md-nav__link"> |
| So, what's changed since 1.6.3? |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#random-facts" class="md-nav__link"> |
| Random facts |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#changes-since-20-beta-5" class="md-nav__link"> |
| Changes since 2.0 Beta 5 |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-20-beta-5-2019-11-25" class="md-nav__link"> |
| Version 2.0 Beta 5 (2019-11-25) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-20-beta-4-2019-11-18" class="md-nav__link"> |
| Version 2.0 Beta 4 (2019-11-18) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-20-beta-3-2019-08-22" class="md-nav__link"> |
| Version 2.0 Beta 3 (2019-08-22) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-20-beta-2-2019-08-02" class="md-nav__link"> |
| Version 2.0 Beta 2 (2019-08-02) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-20-beta-1-2019-07-30" class="md-nav__link"> |
| Version 2.0 Beta 1 (2019-07-30) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-20-alpha-3-2019-07-04" class="md-nav__link"> |
| Version 2.0 Alpha 3 (2019-07-04) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-20-alpha-2-2019-05-21" class="md-nav__link"> |
| Version 2.0 Alpha 2 (2019-05-21) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-20-alpha-1-2019-04-23" class="md-nav__link"> |
| Version 2.0 Alpha 1 (2019-04-23) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-163-2019-01-10" class="md-nav__link"> |
| Version 1.6.3 (2019-01-10) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-162-2018-10-16" class="md-nav__link"> |
| Version 1.6.2 (2018-10-16) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 1.6.2 (2018-10-16)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#public-api-changes" class="md-nav__link"> |
| Public API changes |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-161-2018-06-21" class="md-nav__link"> |
| Version 1.6.1 (2018-06-21) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 1.6.1 (2018-06-21)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#public-api-changes_1" class="md-nav__link"> |
| Public API changes |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-154-2017-09-22" class="md-nav__link"> |
| Version 1.5.4 (2017-09-22) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-153-2017-09-17" class="md-nav__link"> |
| Version 1.5.3 (2017-09-17) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-152-2017-08-09" class="md-nav__link"> |
| Version 1.5.2 (2017-08-09) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-151-2017-04-25" class="md-nav__link"> |
| Version 1.5.1 (2017-04-25) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-15-2016-09-28" class="md-nav__link"> |
| Version 1.5 (2016-09-28) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 1.5 (2016-09-28)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#public-api-changes_2" class="md-nav__link"> |
| Public API changes |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-14-2016-09-11" class="md-nav__link"> |
| Version 1.4 (2016-09-11) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-14-beta2-2016-03-23" class="md-nav__link"> |
| Version 1.4-beta2 (2016-03-23) |
| </a> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-14-beta1-2016-01-08" class="md-nav__link"> |
| Version 1.4-beta1 (2016-01-08) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 1.4-beta1 (2016-01-08)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#public-api-changes_3" class="md-nav__link"> |
| Public API changes |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-131-2015-05-16" class="md-nav__link"> |
| Version 1.3.1 (2015-05-16) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 1.3.1 (2015-05-16)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#public-api-changes_4" class="md-nav__link"> |
| Public API changes |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| <li class="md-nav__item"> |
| <a href="#version-13-2015-05-08" class="md-nav__link"> |
| Version 1.3 (2015-05-08) |
| </a> |
| |
| <nav class="md-nav" aria-label="Version 1.3 (2015-05-08)"> |
| <ul class="md-nav__list"> |
| |
| <li class="md-nav__item"> |
| <a href="#dependencies" class="md-nav__link"> |
| Dependencies |
| </a> |
| |
| </li> |
| |
| </ul> |
| </nav> |
| |
| </li> |
| |
| </ul> |
| |
| </nav> |
| </div> |
| </div> |
| </div> |
| |
| |
| |
| <div class="md-content" data-md-component="content"> |
| <article class="md-content__inner md-typeset"> |
| |
| |
| |
| <span style="float: right">🤔 Documentation issue? <a href="https://github.com/square/leakcanary/issues/new?assignees=&labels=type%3A+documentation&template=4-doc.md&title=Doc%20issue%20with%20changelog/%20page">Report</a> or <a href="https://github.com/square/leakcanary/edit/main/docs/changelog.md">edit</a></span> |
| |
| |
| |
| |
| |
| |
| <h1 id="change-log">Change Log<a class="headerlink" href="#change-log" title="Permanent link">¶</a></h1> |
| <p>Please thank our <a href="https://github.com/square/leakcanary/graphs/contributors">contributors</a> 🙏 🙏 🙏.</p> |
| <h2 id="version-30-alpha-8-2024-06-04">Version 3.0 Alpha 8 (2024-06-04)<a class="headerlink" href="#version-30-alpha-8-2024-06-04" title="Permanent link">¶</a></h2> |
| <ul> |
| <li>Added support for proper hprof handling on heap growth detection failures. Also inlined some public collaborators to achieve that. We now have a single class that’s a bit larger but also a lot more obvious.</li> |
| <li><code>findGrowingObjects</code> does not take a <code>CloseableHeapGraph</code> anymore (just a <code>HeapGraph</code>) and does not close that graph.</li> |
| </ul> |
| <h2 id="version-30-alpha-7-2024-05-30">Version 3.0 Alpha 7 (2024-05-30)<a class="headerlink" href="#version-30-alpha-7-2024-05-30" title="Permanent link">¶</a></h2> |
| <p>Revisited a number of API choices for heap growth, to simplify but also support more advanced |
| behavior such as keep heap dumps on test failure, or zipping heap dumps for CI upload.</p> |
| <ul> |
| <li><code>HeapGrowthTraversal</code> is now <code>HeapDiff</code></li> |
| <li><code>ObjectGrowthDetector.forAndroidHeap().repeatingAndroidInProcessScenario()</code> is now HeapDiff.repeatingAndroidInProcessScenario()<code>which is now really just a wrapper for HeapDiff.repeatingDumpingTestScenario()</code> with Android UI test specific configuration.</li> |
| <li><code>maxHeapDumps</code> and <code>scenarioLoopsPerDump</code> have moved from being factory parameters to being per scenario parameters.</li> |
| <li>💥 <a href="https://github.com/square/leakcanary/pull/2683">#2683</a> Fix crash when java.lang.Object has multiple class load records in JVM heap dumps</li> |
| <li>🔨 <a href="https://github.com/square/leakcanary/pull/2682">#2682</a> Add support for unload class tags and records</li> |
| </ul> |
| <h3 id="heap-growth-espresso-test-example">Heap Growth: Espresso test example<a class="headerlink" href="#heap-growth-espresso-test-example" title="Permanent link">¶</a></h3> |
| <div class="highlight"><pre><span></span><code><span class="n">dependencies</span><span class="w"> </span><span class="o">{</span> |
| <span class="w"> </span><span class="n">androidTestImplementation</span><span class="w"> </span><span class="s1">'com.squareup.leakcanary:leakcanary-android-test:3.0-alpha-7'</span> |
| <span class="o">}</span> |
| </code></pre></div> |
| <div class="highlight"><pre><span></span><code><span class="cp"><?xml version="1.0" encoding="utf-8"?></span> |
| <span class="nt"><manifest</span> |
| <span class="w"> </span><span class="na">xmlns:android=</span><span class="s">"http://schemas.android.com/apk/res/android"</span><span class="nt">></span> |
| |
| <span class="w"> </span><span class="cm"><!-- Performing the heap growth analysis in process requires more heap. --></span> |
| <span class="w"> </span><span class="nt"><application</span> |
| <span class="w"> </span><span class="na">android:largeHeap=</span><span class="s">"true"</span><span class="nt">/></span> |
| <span class="nt"></manifest></span> |
| </code></pre></div> |
| <div class="highlight"><pre><span></span><code><span class="kd">class</span><span class="w"> </span><span class="nc">MyEspressoTest</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">detector</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">HeapDiff</span><span class="p">.</span><span class="na">repeatingAndroidInProcessScenario</span><span class="p">()</span> |
| |
| <span class="w"> </span><span class="nd">@Test</span> |
| <span class="w"> </span><span class="kd">fun</span><span class="w"> </span><span class="nf">greeter_says_hello_does_not_grow_heap</span><span class="p">()</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="c1">// Runs repeatedly until the heap stops growing or we reach max heap dumps.</span> |
| <span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">heapDiff</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">detector</span><span class="p">.</span><span class="na">findRepeatedlyGrowingObjects</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="n">onView</span><span class="p">(</span><span class="n">withId</span><span class="p">(</span><span class="n">R</span><span class="p">.</span><span class="na">id</span><span class="p">.</span><span class="na">name_field</span><span class="p">)).</span><span class="na">perform</span><span class="p">(</span><span class="n">typeText</span><span class="p">(</span><span class="s">"Steve"</span><span class="p">))</span> |
| <span class="w"> </span><span class="n">onView</span><span class="p">(</span><span class="n">withId</span><span class="p">(</span><span class="n">R</span><span class="p">.</span><span class="na">id</span><span class="p">.</span><span class="na">greet_button</span><span class="p">)).</span><span class="na">perform</span><span class="p">(</span><span class="n">click</span><span class="p">())</span> |
| <span class="w"> </span><span class="n">onView</span><span class="p">(</span><span class="n">withText</span><span class="p">(</span><span class="s">"Hello Steve!"</span><span class="p">)).</span><span class="na">check</span><span class="p">(</span><span class="n">matches</span><span class="p">(</span><span class="n">isDisplayed</span><span class="p">()))</span> |
| <span class="w"> </span><span class="p">}</span> |
| |
| <span class="w"> </span><span class="n">assertThat</span><span class="p">(</span><span class="n">heapDiff</span><span class="p">.</span><span class="na">growingObjects</span><span class="p">).</span><span class="na">isEmpty</span><span class="p">()</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="p">}</span> |
| </code></pre></div> |
| <h3 id="heap-growth-jvm-junit-test-example">Heap Growth: JVM Junit test example.<a class="headerlink" href="#heap-growth-jvm-junit-test-example" title="Permanent link">¶</a></h3> |
| <div class="highlight"><pre><span></span><code><span class="n">dependencies</span><span class="w"> </span><span class="o">{</span> |
| <span class="w"> </span><span class="n">androidTestImplementation</span><span class="w"> </span><span class="s1">'com.squareup.leakcanary:leakcanary-jvm-test:3.0-alpha-7'</span> |
| <span class="o">}</span> |
| </code></pre></div> |
| <div class="highlight"><pre><span></span><code><span class="kd">class</span><span class="w"> </span><span class="nc">MyUnitTest</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">detector</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">HeapDiff</span><span class="p">.</span><span class="na">repeatingJvmInProcessScenario</span><span class="p">()</span> |
| |
| <span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">growingList</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">mutableListOf</span><span class="o"><</span><span class="kt">String</span><span class="o">></span><span class="p">()</span> |
| |
| <span class="w"> </span><span class="nd">@Test</span> |
| <span class="w"> </span><span class="kd">fun</span><span class="w"> </span><span class="nf">failing_test</span><span class="p">()</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="c1">// Runs repeatedly until the heap stops growing or we reach max heap dumps.</span> |
| <span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">heapDiff</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">detector</span><span class="p">.</span><span class="na">findRepeatedlyGrowingObjects</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="n">growingList</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="s">"Hi at </span><span class="si">${</span><span class="n">System</span><span class="p">.</span><span class="na">currentTimeMillis</span><span class="p">()</span><span class="si">}</span><span class="s">"</span> |
| <span class="w"> </span><span class="p">}</span> |
| |
| <span class="w"> </span><span class="c1">// This should fail.</span> |
| <span class="w"> </span><span class="n">assertThat</span><span class="p">(</span><span class="n">heapDiff</span><span class="p">.</span><span class="na">growingObjects</span><span class="p">).</span><span class="na">isEmpty</span><span class="p">()</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="p">}</span> |
| </code></pre></div> |
| <h3 id="heap-growth-ui-automator-test-example">Heap Growth: UI Automator test example.<a class="headerlink" href="#heap-growth-ui-automator-test-example" title="Permanent link">¶</a></h3> |
| <div class="highlight"><pre><span></span><code><span class="n">dependencies</span><span class="w"> </span><span class="o">{</span> |
| <span class="w"> </span><span class="n">androidTestImplementation</span><span class="w"> </span><span class="s1">'com.squareup.leakcanary:leakcanary-android-uiautomator:3.0-alpha-7'</span> |
| <span class="o">}</span> |
| </code></pre></div> |
| <div class="highlight"><pre><span></span><code><span class="kd">class</span><span class="w"> </span><span class="nc">MyUiAutomatorTest</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">detector</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">HeapDiff</span><span class="p">.</span><span class="na">repeatingUiAutomatorScenario</span><span class="p">()</span> |
| |
| <span class="w"> </span><span class="nd">@Test</span> |
| <span class="w"> </span><span class="kd">fun</span><span class="w"> </span><span class="nf">clicking_welcome_does_not_grow_heap</span><span class="p">()</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">device</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">UiDevice</span><span class="p">.</span><span class="na">getInstance</span><span class="p">(</span><span class="n">InstrumentationRegistry</span><span class="p">.</span><span class="na">getInstrumentation</span><span class="p">())</span> |
| <span class="w"> </span><span class="c1">// Runs repeatedly until the heap stops growing or we reach max heap dumps.</span> |
| <span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">heapDiff</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">detector</span><span class="p">.</span><span class="na">findRepeatedlyGrowingObjects</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="n">device</span><span class="p">.</span><span class="na">findObject</span><span class="p">(</span><span class="n">By</span><span class="p">.</span><span class="na">text</span><span class="p">(</span><span class="s">"Welcome!"</span><span class="p">)).</span><span class="na">click</span><span class="p">()</span> |
| <span class="w"> </span><span class="p">}</span> |
| |
| <span class="w"> </span><span class="n">assertThat</span><span class="p">(</span><span class="n">heapDiff</span><span class="p">.</span><span class="na">growingObjects</span><span class="p">).</span><span class="na">isEmpty</span><span class="p">()</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="p">}</span> |
| </code></pre></div> |
| <h3 id="heap-growth-shark-cli">Heap Growth: Shark CLI<a class="headerlink" href="#heap-growth-shark-cli" title="Permanent link">¶</a></h3> |
| <p>Download the <a href="https://github.com/square/leakcanary/releases/download/v3.0-alpha-7/shark-cli-3.0-alpha-7.zip">Shark CLI Zip</a> (alphas cannot be released to brew) and unzip it.</p> |
| <p>Run the <code>heap-growth</code> command:</p> |
| <div class="highlight"><pre><span></span><code>$ ~/Downloads/shark-cli-3.0-alpha-7/bin/shark-cli -p com.example.app.debug heap-growth |
| </code></pre></div> |
| <p>See the <a href="https://github.com/square/leakcanary/compare/v3.0-alpha-6...v3.0-alpha-7">full diff</a>.</p> |
| <h2 id="version-30-alpha-6-2024-05-21">Version 3.0 Alpha 6 (2024-05-21)<a class="headerlink" href="#version-30-alpha-6-2024-05-21" title="Permanent link">¶</a></h2> |
| <ul> |
| <li>🐛 <a href="https://github.com/square/leakcanary/pull/2670">#2670</a> Use <code>RequestPermissionActivity</code> context for <code>Toast.makeText</code>.</li> |
| </ul> |
| <h3 id="heap-growth">Heap Growth<a class="headerlink" href="#heap-growth" title="Permanent link">¶</a></h3> |
| <ul> |
| <li>Add warmup to reduce changes of classloading tied to analysis being picked up as false positive heap growth signal.</li> |
| <li>Add dependency on AndroidX Collections to use in place of JDK data structures (lower memory footprint) and HHPC copied data structures (hard to maintain).</li> |
| <li>Improvements to memory footprint by flattening a number of objects</li> |
| <li>Fix retained size not being computed when analysis stops at the second heap dump.</li> |
| <li>Removed <code>InitialState.heapGraphCount</code></li> |
| <li>Ignore static <code><resolved_references></code> in all classes on JVM</li> |
| </ul> |
| <p>See the <a href="https://github.com/square/leakcanary/compare/v3.0-alpha-4...v3.0-alpha-6">full diff</a>.</p> |
| <h2 id="version-30-alpha-4-2024-05-10">Version 3.0 Alpha 4 (2024-05-10)<a class="headerlink" href="#version-30-alpha-4-2024-05-10" title="Permanent link">¶</a></h2> |
| <ul> |
| <li>Deleted the <code>shark-heap-growth</code> artifact, the code has been merged into the <code>shark*</code> and <code>leakcanary*</code> modules.</li> |
| <li>New <code>leakcanary-android-test</code> and <code>leakcanary-android-uiautomator</code> artifacts.</li> |
| <li>Undo of breaking API changes that were introduced in alpha 1. The goal is to make the upgrade seamless. Please file an issue if you find an API breaking change from a 2.x release.</li> |
| <li>Optimization: for known data structures that don’t reference the rest of the graph beyond the references we |
| know about, we explore them locally at once and stop enqueuing their internals, which reduces the memory |
| footprint and the IO reads.</li> |
| <li>Revamped the heap growth detection APIs, added support for UI Automator and Shark CLI.</li> |
| </ul> |
| <p>(<em>note: I skipped from alpha 1 to alpha 4 because I messed up a few releases. Sorry!</em>)</p> |
| <h3 id="heap-growth-espresso-test-example_1">Heap Growth: Espresso test example<a class="headerlink" href="#heap-growth-espresso-test-example_1" title="Permanent link">¶</a></h3> |
| <p>Add the dependency:</p> |
| <div class="highlight"><pre><span></span><code><span class="n">dependencies</span><span class="w"> </span><span class="o">{</span> |
| <span class="w"> </span><span class="n">androidTestImplementation</span><span class="w"> </span><span class="s1">'com.squareup.leakcanary:leakcanary-android-test:3.0-alpha-2'</span> |
| <span class="o">}</span> |
| </code></pre></div> |
| <p>Ensure your UI tests have enough heap by updating <code>src/androidTest/AndroidManifest.xml</code>:</p> |
| <div class="highlight"><pre><span></span><code><span class="cp"><?xml version="1.0" encoding="utf-8"?></span> |
| <span class="nt"><manifest</span> |
| <span class="w"> </span><span class="na">xmlns:android=</span><span class="s">"http://schemas.android.com/apk/res/android"</span><span class="nt">></span> |
| |
| <span class="w"> </span><span class="cm"><!-- Performing the heap growth analysis in process requires more heap. --></span> |
| <span class="w"> </span><span class="nt"><application</span> |
| <span class="w"> </span><span class="na">android:largeHeap=</span><span class="s">"true"</span><span class="nt">/></span> |
| <span class="nt"></manifest></span> |
| </code></pre></div> |
| <div class="highlight"><pre><span></span><code><span class="kd">class</span><span class="w"> </span><span class="nc">MyEspressoTest</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">detector</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ObjectGrowthDetector</span> |
| <span class="w"> </span><span class="p">.</span><span class="na">forAndroidHeap</span><span class="p">()</span> |
| <span class="w"> </span><span class="p">.</span><span class="na">repeatingAndroidInProcessScenario</span><span class="p">()</span> |
| |
| <span class="w"> </span><span class="nd">@Test</span> |
| <span class="w"> </span><span class="kd">fun</span><span class="w"> </span><span class="nf">greeter_says_hello_does_not_leak</span><span class="p">()</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="c1">// Runs repeatedly until the heap stops growing or we reach max heap dumps.</span> |
| <span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">heapGrowth</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">detector</span><span class="p">.</span><span class="na">findRepeatedlyGrowingObjects</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="n">onView</span><span class="p">(</span><span class="n">withId</span><span class="p">(</span><span class="n">R</span><span class="p">.</span><span class="na">id</span><span class="p">.</span><span class="na">name_field</span><span class="p">)).</span><span class="na">perform</span><span class="p">(</span><span class="n">typeText</span><span class="p">(</span><span class="s">"Steve"</span><span class="p">))</span> |
| <span class="w"> </span><span class="n">onView</span><span class="p">(</span><span class="n">withId</span><span class="p">(</span><span class="n">R</span><span class="p">.</span><span class="na">id</span><span class="p">.</span><span class="na">greet_button</span><span class="p">)).</span><span class="na">perform</span><span class="p">(</span><span class="n">click</span><span class="p">())</span> |
| <span class="w"> </span><span class="n">onView</span><span class="p">(</span><span class="n">withText</span><span class="p">(</span><span class="s">"Hello Steve!"</span><span class="p">)).</span><span class="na">check</span><span class="p">(</span><span class="n">matches</span><span class="p">(</span><span class="n">isDisplayed</span><span class="p">()))</span> |
| <span class="w"> </span><span class="p">}</span> |
| |
| <span class="w"> </span><span class="n">assertThat</span><span class="p">(</span><span class="n">heapGrowth</span><span class="p">.</span><span class="na">growingObjects</span><span class="p">).</span><span class="na">isEmpty</span><span class="p">()</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="p">}</span> |
| </code></pre></div> |
| <h3 id="heap-growth-ui-automator-test-example_1">Heap Growth: UI Automator test example.<a class="headerlink" href="#heap-growth-ui-automator-test-example_1" title="Permanent link">¶</a></h3> |
| <p>Add the dependency:</p> |
| <div class="highlight"><pre><span></span><code><span class="n">dependencies</span><span class="w"> </span><span class="o">{</span> |
| <span class="w"> </span><span class="n">androidTestImplementation</span><span class="w"> </span><span class="s1">'com.squareup.leakcanary:leakcanary-android-uiautomator:3.0-alpha-4'</span> |
| <span class="o">}</span> |
| </code></pre></div> |
| <div class="highlight"><pre><span></span><code><span class="kd">class</span><span class="w"> </span><span class="nc">MyUiAutomatorTest</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">detector</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ObjectGrowthDetector</span> |
| <span class="w"> </span><span class="p">.</span><span class="na">forAndroidHeap</span><span class="p">()</span> |
| <span class="w"> </span><span class="p">.</span><span class="na">repeatingUiAutomatorScenario</span><span class="p">()</span> |
| |
| <span class="w"> </span><span class="nd">@Test</span> |
| <span class="w"> </span><span class="kd">fun</span><span class="w"> </span><span class="nf">clicking_welcome_does_not_leak</span><span class="p">()</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">device</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">UiDevice</span><span class="p">.</span><span class="na">getInstance</span><span class="p">(</span><span class="n">InstrumentationRegistry</span><span class="p">.</span><span class="na">getInstrumentation</span><span class="p">())</span> |
| <span class="w"> </span><span class="c1">// Runs repeatedly until the heap stops growing or we reach max heap dumps.</span> |
| <span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">heapGrowth</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">detector</span><span class="p">.</span><span class="na">findRepeatedlyGrowingObjects</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="n">device</span><span class="p">.</span><span class="na">findObject</span><span class="p">(</span><span class="n">By</span><span class="p">.</span><span class="na">text</span><span class="p">(</span><span class="s">"Welcome!"</span><span class="p">)).</span><span class="na">click</span><span class="p">()</span> |
| <span class="w"> </span><span class="p">}</span> |
| |
| <span class="w"> </span><span class="n">assertThat</span><span class="p">(</span><span class="n">heapGrowth</span><span class="p">.</span><span class="na">growingObjects</span><span class="p">).</span><span class="na">isEmpty</span><span class="p">()</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="p">}</span> |
| </code></pre></div> |
| <h3 id="heap-growth-shark-cli_1">Heap Growth: Shark CLI<a class="headerlink" href="#heap-growth-shark-cli_1" title="Permanent link">¶</a></h3> |
| <p>Download the <a href="https://github.com/square/leakcanary/releases/download/v3.0-alpha-4/shark-cli-3.0-alpha-4.zip">Shark CLI Zip</a> (alphas cannot be released to brew) and unzip it.</p> |
| <p>Run the <code>heap-growth</code> command:</p> |
| <div class="highlight"><pre><span></span><code>$ ~/Downloads/shark-cli-3.0-alpha-2/bin/shark-cli -p com.example.app.debug heap-growth |
| </code></pre></div> |
| <h2 id="version-214-2024-04-17">Version 2.14 (2024-04-17)<a class="headerlink" href="#version-214-2024-04-17" title="Permanent link">¶</a></h2> |
| <ul> |
| <li>🐛 <a href="https://github.com/square/leakcanary/issues/2650">#2650</a> Removed accidental usage of <code>SettableFuture</code>, a <code>WorkManager</code> internal class, which will be removed in a <strong>future release</strong> of WorkManager. After updating WorkManager to that future release, <strong>all versions of LeakCanary from 2.8 to 2.13 will crash on leak analysis</strong>. To avoid a nasty surprise in the near future, <strong>update to LeakCanary 2.14</strong>.</li> |
| <li>🔨 <a href="https://github.com/square/leakcanary/pull/2660">#2660</a> Add proguard mapping support for LeakCanary release.</li> |
| <li>🐛 <a href="https://github.com/square/leakcanary/issues/2531">#2531</a> Heap dump & leak lists not preserving list position when navigating.</li> |
| <li>🐤 <a href="https://github.com/square/leakcanary/pull/2615">#2615</a> Automatic fix of AOSP PermissionControllerManager leak (<a href="https://issuetracker.google.com/issues/318415056">issuetracker.google.com/issues/318415056</a>).</li> |
| <li>🐤 <a href="https://github.com/square/leakcanary/issues/2559">#2559</a> Ignore <code>UiModeManager</code> AOSP leak.</li> |
| <li>💥 <a href="https://github.com/square/leakcanary/issues/2643">#2643</a> Fixed rare crash on RenderHeapDumpScreen.</li> |
| </ul> |
| <h2 id="version-30-alpha-1-2024-01-09">Version 3.0 Alpha 1 (2024-01-09)<a class="headerlink" href="#version-30-alpha-1-2024-01-09" title="Permanent link">¶</a></h2> |
| <p>This alpha release marks the start of the work on LeakCanary 3. It’s not stable! While I intend to rework some APIs, I also want to minimize migration work. The best way to ensure migrations will go smoothly is to try upgrading to a 3.0 alpha and to let me know if you get any compile or runtime error.</p> |
| <h3 id="heap-growth_1">Heap Growth<a class="headerlink" href="#heap-growth_1" title="Permanent link">¶</a></h3> |
| <p>New APIs, not stable yet: the <code>shark-heap-growth</code> artifact contains APIs for writing test scenarios that detect repeated heap growth.</p> |
| <p>Here’s how it’s used with an Espresso test:</p> |
| <div class="highlight"><pre><span></span><code><span class="kd">class</span><span class="w"> </span><span class="nc">MyEspressoTest</span><span class="w"> </span><span class="p">{</span> |
| |
| <span class="w"> </span><span class="nd">@Test</span> |
| <span class="w"> </span><span class="kd">fun</span><span class="w"> </span><span class="nf">greeter_says_hello_does_not_leak</span><span class="p">()</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="c1">// Runs in a loop until the heap stops growing or we reach max heap dumps.</span> |
| <span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">heapTraversal</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">HeapGrowthDetector</span><span class="p">.</span><span class="na">detectRepeatedHeapGrowth</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="c1">// Runs repeatedly until the heap stops growing or we reach maxHeapDumps.</span> |
| <span class="w"> </span><span class="n">onView</span><span class="p">(</span><span class="n">withId</span><span class="p">(</span><span class="n">R</span><span class="p">.</span><span class="na">id</span><span class="p">.</span><span class="na">name_field</span><span class="p">)).</span><span class="na">perform</span><span class="p">(</span><span class="n">typeText</span><span class="p">(</span><span class="s">"Steve"</span><span class="p">))</span> |
| <span class="w"> </span><span class="n">onView</span><span class="p">(</span><span class="n">withId</span><span class="p">(</span><span class="n">R</span><span class="p">.</span><span class="na">id</span><span class="p">.</span><span class="na">greet_button</span><span class="p">)).</span><span class="na">perform</span><span class="p">(</span><span class="n">click</span><span class="p">())</span> |
| <span class="w"> </span><span class="n">onView</span><span class="p">(</span><span class="n">withText</span><span class="p">(</span><span class="s">"Hello Steve!"</span><span class="p">)).</span><span class="na">check</span><span class="p">(</span><span class="n">matches</span><span class="p">(</span><span class="n">isDisplayed</span><span class="p">()))</span> |
| <span class="w"> </span><span class="p">}</span> |
| |
| <span class="w"> </span><span class="n">assertThat</span><span class="p">(</span><span class="n">heapTraversal</span><span class="p">.</span><span class="na">growingNodes</span><span class="p">).</span><span class="na">isEmpty</span><span class="p">()</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="p">}</span> |
| </code></pre></div> |
| <p>Here’s an example set up, this is all very manual for now.</p> |
| <p>Add the new dependency:</p> |
| <div class="highlight"><pre><span></span><code><span class="n">dependencies</span><span class="w"> </span><span class="o">{</span> |
| <span class="w"> </span><span class="n">androidTestImplementation</span><span class="w"> </span><span class="s1">'com.squareup.leakcanary:shark-heap-growth:3.0-alpha-1'</span> |
| <span class="w"> </span><span class="n">androidTestImplementation</span><span class="w"> </span><span class="s1">'com.squareup.leakcanary:leakcanary-android-core:3.0-alpha-1'</span> |
| <span class="o">}</span> |
| </code></pre></div> |
| <p>Create an implementation setup for Espresso in process UI tests:</p> |
| <div class="highlight"><pre><span></span><code><span class="k">import</span><span class="w"> </span><span class="nn">leakcanary.AndroidDebugHeapDumper</span> |
| <span class="k">import</span><span class="w"> </span><span class="nn">shark.AndroidReferenceMatchers</span> |
| <span class="k">import</span><span class="w"> </span><span class="nn">shark.AndroidReferenceReaderFactory</span> |
| <span class="k">import</span><span class="w"> </span><span class="nn">shark.CloseableHeapGraph</span> |
| <span class="k">import</span><span class="w"> </span><span class="nn">shark.DiffingHeapGrowthDetector</span> |
| <span class="k">import</span><span class="w"> </span><span class="nn">shark.HeapGraphProvider</span> |
| <span class="k">import</span><span class="w"> </span><span class="nn">shark.HeapTraversal</span> |
| <span class="k">import</span><span class="w"> </span><span class="nn">shark.HprofHeapGraph.Companion.openHeapGraph</span> |
| <span class="k">import</span><span class="w"> </span><span class="nn">shark.IgnoredReferenceMatcher</span> |
| <span class="k">import</span><span class="w"> </span><span class="nn">shark.LiveHeapGrowthDetector</span> |
| <span class="k">import</span><span class="w"> </span><span class="nn">shark.LoopingHeapGrowthDetector</span> |
| <span class="k">import</span><span class="w"> </span><span class="nn">shark.MatchingGcRootProvider</span> |
| <span class="k">import</span><span class="w"> </span><span class="nn">shark.ReferencePattern.InstanceFieldPattern</span> |
| <span class="k">import</span><span class="w"> </span><span class="nn">java.io.File</span> |
| <span class="k">import</span><span class="w"> </span><span class="nn">java.text.SimpleDateFormat</span> |
| <span class="k">import</span><span class="w"> </span><span class="nn">java.util.Date</span> |
| <span class="k">import</span><span class="w"> </span><span class="nn">java.util.Locale</span> |
| |
| <span class="cm">/**</span> |
| <span class="cm"> * Heap growth detector for in process Espresso UI tests.</span> |
| <span class="cm"> *</span> |
| <span class="cm"> * Call [LiveHeapGrowthDetector.detectRepeatedHeapGrowth] with a scenario to repeat,</span> |
| <span class="cm"> * then assert that the resulting [shark.HeapTraversalWithDiff.growingNodes] is empty.</span> |
| <span class="cm"> */</span> |
| <span class="kd">val</span><span class="w"> </span><span class="nv">HeapGrowthDetector</span><span class="w"> </span><span class="k">by</span><span class="w"> </span><span class="n">lazy</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">referenceMatchers</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">AndroidReferenceMatchers</span><span class="p">.</span><span class="na">appDefaults</span><span class="w"> </span><span class="o">+</span> |
| <span class="w"> </span><span class="n">HeapTraversal</span><span class="p">.</span><span class="na">ignoredReferences</span><span class="w"> </span><span class="o">+</span> |
| <span class="w"> </span><span class="c1">// https://cs.android.com/android/_/android/platform/frameworks/base/+/6985fb39f07294fb979b14ba0ebabfd2fea06d34</span> |
| <span class="w"> </span><span class="n">IgnoredReferenceMatcher</span><span class="p">(</span><span class="n">InstanceFieldPattern</span><span class="p">(</span><span class="s">"android.os.StrictMode"</span><span class="p">,</span><span class="w"> </span><span class="s">"sLastVmViolationTime"</span><span class="p">))</span> |
| |
| <span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">dateFormat</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">SimpleDateFormat</span><span class="p">(</span><span class="s">"yyyy-MM-dd_HH-mm-ss_SSS'-heap-growth.hprof'"</span><span class="p">,</span><span class="w"> </span><span class="n">Locale</span><span class="p">.</span><span class="na">US</span><span class="p">)</span> |
| <span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">uploadedTracesDirectory</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">File</span><span class="p">(</span><span class="s">"/sdcard/traces/"</span><span class="p">)</span> |
| <span class="w"> </span><span class="n">uploadedTracesDirectory</span><span class="p">.</span><span class="na">mkdirs</span><span class="p">()</span> |
| <span class="w"> </span><span class="n">check</span><span class="p">(</span><span class="n">uploadedTracesDirectory</span><span class="p">.</span><span class="na">exists</span><span class="p">())</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="s">"Expected heap dump folder to exist: </span><span class="si">${</span><span class="n">uploadedTracesDirectory</span><span class="p">.</span><span class="na">absolutePath</span><span class="si">}</span><span class="s">"</span> |
| <span class="w"> </span><span class="p">}</span> |
| |
| <span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">heapGraphProvider</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">HeapGraphProvider</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">fileName</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">dateFormat</span><span class="p">.</span><span class="na">format</span><span class="p">(</span><span class="n">Date</span><span class="p">())</span> |
| <span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">heapDumpFile</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">File</span><span class="p">(</span><span class="n">uploadedTracesDirectory</span><span class="p">,</span><span class="w"> </span><span class="n">fileName</span><span class="p">)</span> |
| <span class="w"> </span><span class="n">AndroidDebugHeapDumper</span><span class="p">.</span><span class="na">dumpHeap</span><span class="p">(</span><span class="n">heapDumpFile</span><span class="p">)</span> |
| <span class="w"> </span><span class="n">check</span><span class="p">(</span><span class="n">heapDumpFile</span><span class="p">.</span><span class="na">exists</span><span class="p">())</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="s">"Expected file to exist after heap dump: </span><span class="si">${</span><span class="n">heapDumpFile</span><span class="p">.</span><span class="na">absolutePath</span><span class="si">}</span><span class="s">"</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">realGraph</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">heapDumpFile</span><span class="p">.</span><span class="na">openHeapGraph</span><span class="p">()</span> |
| <span class="w"> </span><span class="k">object</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nc">CloseableHeapGraph</span><span class="w"> </span><span class="k">by</span><span class="w"> </span><span class="n">realGraph</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="kd">override</span><span class="w"> </span><span class="kd">fun</span><span class="w"> </span><span class="nf">close</span><span class="p">()</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="n">realGraph</span><span class="p">.</span><span class="na">close</span><span class="p">()</span> |
| <span class="w"> </span><span class="n">heapDumpFile</span><span class="p">.</span><span class="na">delete</span><span class="p">()</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="w"> </span><span class="p">}</span> |
| |
| <span class="w"> </span><span class="n">LiveHeapGrowthDetector</span><span class="p">(</span> |
| <span class="w"> </span><span class="n">maxHeapDumps</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">5</span><span class="p">,</span> |
| <span class="w"> </span><span class="n">heapGraphProvider</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">heapGraphProvider</span><span class="p">,</span> |
| <span class="w"> </span><span class="n">scenarioLoopsPerDump</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">5</span><span class="p">,</span> |
| <span class="w"> </span><span class="n">detector</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">LoopingHeapGrowthDetector</span><span class="p">(</span> |
| <span class="w"> </span><span class="n">DiffingHeapGrowthDetector</span><span class="p">(</span> |
| <span class="w"> </span><span class="n">referenceReaderFactory</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">AndroidReferenceReaderFactory</span><span class="p">(</span><span class="n">referenceMatchers</span><span class="p">),</span> |
| <span class="w"> </span><span class="n">gcRootProvider</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">MatchingGcRootProvider</span><span class="p">(</span><span class="n">referenceMatchers</span><span class="p">)</span> |
| <span class="w"> </span><span class="p">)</span> |
| <span class="w"> </span><span class="p">)</span> |
| <span class="w"> </span><span class="p">)</span> |
| <span class="p">}</span> |
| </code></pre></div> |
| <p>Ensure your UI tests have enough heap by updating <code>src/androidTest/AndroidManifest.xml</code>:</p> |
| <div class="highlight"><pre><span></span><code><span class="cp"><?xml version="1.0" encoding="utf-8"?></span> |
| <span class="nt"><manifest</span> |
| <span class="w"> </span><span class="na">xmlns:android=</span><span class="s">"http://schemas.android.com/apk/res/android"</span><span class="nt">></span> |
| |
| <span class="w"> </span><span class="cm"><!-- Performing the heap growth analysis in process requires more heap. --></span> |
| <span class="w"> </span><span class="nt"><application</span> |
| <span class="w"> </span><span class="na">android:largeHeap=</span><span class="s">"true"</span><span class="nt">/></span> |
| <span class="nt"></manifest></span> |
| </code></pre></div> |
| <h3 id="reference-readers">Reference readers<a class="headerlink" href="#reference-readers" title="Permanent link">¶</a></h3> |
| <p>New APIs, not stable yet: <code>ReferenceReader</code> implementations aka expanders, are now public APIs. The names might change. These class define how LeakCanary traverses the graph, and allow for the creating of virtual references, as <a href="#improved-support-for-data-structure-internals">introduced here</a>. These new APIs make it possible to add support for more custom data structures, and they’re also useful when working directly with the <code>shark</code> APIs (for example, these APIs were necessary to build the heap growth detection tooling mentioned above).</p> |
| <h3 id="objectwatcher-apis-refactor">ObjectWatcher APIs refactor<a class="headerlink" href="#objectwatcher-apis-refactor" title="Permanent link">¶</a></h3> |
| <p><a href="https://github.com/square/leakcanary/pull/2612">#2612</a> is a first attempt at refactoring the reachability APIs. I already found backward compatibility issues (<a href="https://github.com/square/leakcanary/issues/2617">#2617</a>), will fix in the next alpha, and probably still change the API shape.</p> |
| <p>The general purpose of this refactor is to move away from the static singletons and high coupling of the current implementation, making the reachability APIs more useful in a variaty of contexts.</p> |
| <h3 id="other-bug-fixes-and-improvements">Other bug fixes and improvements 🐛🔨<a class="headerlink" href="#other-bug-fixes-and-improvements" title="Permanent link">¶</a></h3> |
| <ul> |
| <li>Bumped Kotlin to 1.8.21</li> |
| <li>Dropped support for detecting support fragment leaks: apps should all have migrated to Android X by now, and if not they can easily add their own implementation back.</li> |
| </ul> |
| <p>This list reflects only a subset of all changes. For more details, the <a href="https://github.com/square/leakcanary/compare/v2.13...v3.0-alpha-1">full diff</a>.</p> |
| <h2 id="version-213-2024-01-03">Version 2.13 (2024-01-03)<a class="headerlink" href="#version-213-2024-01-03" title="Permanent link">¶</a></h2> |
| <ul> |
| <li>🐛 <a href="https://github.com/square/leakcanary/issues/2565">#2565</a> Fix AndroidX Fragments incorrectly marked as leaking if detached but not destroyed.</li> |
| <li>💥 <a href="https://github.com/square/leakcanary/issues/2568">#2568</a> Fixed missing <code>RECEIVER_EXPORTED</code> flag when calling <code>registerReceiver()</code> on API 34+.</li> |
| <li>🔨 <a href="https://github.com/square/leakcanary/issues/2555">#2555</a> Binder stubs are now called out in leak traces.</li> |
| <li>🐤 <a href="https://github.com/square/leakcanary/pull/2601">#2601</a> Added several known manufacturer & framework leaks.</li> |
| </ul> |
| <h2 id="version-212-2023-06-29">Version 2.12 (2023-06-29)<a class="headerlink" href="#version-212-2023-06-29" title="Permanent link">¶</a></h2> |
| <ul> |
| <li>💥 <a href="https://github.com/square/leakcanary/issues/2527">#2527</a> <code>LifecycleRegistry</code> in <code>androidx.lifecycle:lifecycle-runtime</code> was migrated to kotlin and its <code>mState</code> field name changed to <code>state</code> which broke LeakCanary expectations.</li> |
| <li>🐤 <a href="https://github.com/square/leakcanary/pull/2545">#2545</a> Added several known manufacturer & framework leaks.</li> |
| </ul> |
| <h2 id="version-211-2023-05-17">Version 2.11 (2023-05-17)<a class="headerlink" href="#version-211-2023-05-17" title="Permanent link">¶</a></h2> |
| <ul> |
| <li>🐛 <a href="https://github.com/square/leakcanary/issues/1764">#1764</a> Ignore phantom classes that were unloaded than reloaded (long time LeakCanary bug).</li> |
| <li>🐛 <a href="https://github.com/square/leakcanary/issues/2471">#2471</a> Fix LeakCanary introducing a weird leak in Google’s CI infra.</li> |
| <li>🐛 <a href="https://github.com/square/leakcanary/issues/2496">#2496</a> Fix broken ViewModel leak detection</li> |
| </ul> |
| <h2 id="version-210-2022-11-10">Version 2.10 (2022-11-10)<a class="headerlink" href="#version-210-2022-11-10" title="Permanent link">¶</a></h2> |
| <h3 id="experimental-neo4j-heap-dump-exploration">Experimental Neo4j heap dump exploration<a class="headerlink" href="#experimental-neo4j-heap-dump-exploration" title="Permanent link">¶</a></h3> |
| <p><code>shark-cli</code> has a new experiment <code>neo4j</code> command that will convert a heap dump into an embedded Neo4j database and then open Neo4j Browser to explore the heap dump.</p> |
| <div class="highlight"><pre><span></span><code>brew install leakcanary-shark |
| |
| shark-cli --process com.example.app.debug neo4j |
| </code></pre></div> |
| <p><img alt="Neo4J heap dump" src="https://user-images.githubusercontent.com/557033/200693468-aa783bb4-9a5a-4a41-8b92-582d44b31b92.png" /></p> |
| <h3 id="other-bug-fixes-and-improvements_1">Other bug fixes and improvements 🐛🔨<a class="headerlink" href="#other-bug-fixes-and-improvements_1" title="Permanent link">¶</a></h3> |
| <ul> |
| <li>🐤 <a href="https://github.com/square/leakcanary/pull/2440">#2440</a> Add Android 13 <code>POST_NOTICICATIONS</code> permission as well as a new <code>LeakCanary.Config.showNotifications</code> config to disable notifications entirely.</li> |
| <li>🐤 <a href="https://github.com/square/leakcanary/pull/2416">#2416</a> Add Android 13 monochrome icon.</li> |
| <li>💥 <a href="https://github.com/square/leakcanary/issues/2371">#2371</a> Fix db crash when navigating heap dump screen.</li> |
| <li>🐛 <a href="https://github.com/square/leakcanary/issues/2393">#2393</a> Allow LeakCanary to be defined as an AndroidX Startup dependency.</li> |
| <li>💥 <a href="https://github.com/square/leakcanary/issues/2430">#2430</a> Fix ShortcutManager crash on Android TV.</li> |
| <li>💥 <a href="https://github.com/square/leakcanary/issues/2382">#2382</a> Fix heap dump close crash.</li> |
| </ul> |
| <p>This list reflects only a subset of all changes. For more details, see the <a href="https://github.com/square/leakcanary/milestone/25">2.10 Milestone</a> and the <a href="https://github.com/square/leakcanary/compare/v2.9.1...v2.10">full diff</a>.</p> |
| <h2 id="version-291-2022-04-20">Version 2.9.1 (2022-04-20)<a class="headerlink" href="#version-291-2022-04-20" title="Permanent link">¶</a></h2> |
| <h3 id="preface">Preface<a class="headerlink" href="#preface" title="Permanent link">¶</a></h3> |
| <p>What are some things you’d like to see in a future LeakCanary 3 version? Tell me <a href="https://twitter.com/Piwai">on Twitter</a>!</p> |
| <p>Some ideas I’m playing with:</p> |
| <ul> |
| <li>Moving heap analysis leak visualisation to a separate single app (written with Compose!) available on the PlayStore.</li> |
| <li>Bumping Okio to 3.0</li> |
| <li>Multiplatform heap analysis? Analyze a JVM heap dump in your browser?!</li> |
| <li>Visualize the heap dominators / retained size as a treemap.</li> |
| <li>A backend for LeakCanary?</li> |
| </ul> |
| <p>Anyway, that’s still very much the future, let’s talk about what’s in <code>2.9.1</code> now!</p> |
| <h3 id="new-metrics-in-heap-analysis-metadata">New metrics in heap analysis metadata<a class="headerlink" href="#new-metrics-in-heap-analysis-metadata" title="Permanent link">¶</a></h3> |
| <p>I built LeakCanary to help fix leaks, but in doing so I accidentally wrote a fairly flexible heap dump parser. Since we’re parsing the heap to find leaks anyway, we might as well report additional interesting metrics. Here’s what you’ll now see in the heap dump metadata:</p> |
| <ul> |
| <li>Class count: count of loaded classes</li> |
| <li>Instance count</li> |
| <li>Primitive array count</li> |
| <li>Object array count</li> |
| <li>Thread count</li> |
| <li>Heap total bytes</li> |
| <li>Bitmap count</li> |
| <li>Bitmap total bytes</li> |
| <li>Large bitmap count (bitmaps with more pixels than 1.1x the pixels on screen)</li> |
| <li>Large bitmap total bytes</li> |
| <li>SQLiteDatabase in memory (open or closed, as well as their file path)</li> |
| </ul> |
| <p>This is just a first pass, feedback and ideas welcome!</p> |
| <h3 id="performance-improvements">Performance improvements<a class="headerlink" href="#performance-improvements" title="Permanent link">¶</a></h3> |
| <p>The heap analysis now traverses the heap dump using <code>RandomAccessFile</code> instead of <code>FileChannel.transferTo()</code> and is now 40% faster on API 23 and 20% faster on newer APIs. |
| Also, sticky class GC roots are now deduplicated, which great reduces the memory footprint of LeakCanary on API 23 (<a href="https://github.com/square/leakcanary/pull/2324">#2324</a>). You can read about the related investigation <a href="https://py.hashnode.dev/of-sharks-and-heaps-of-sticky-marshmallows">on py.hashnode.dev</a>.</p> |
| <h3 id="breaking-change-failtestonleakrunlistener-deleted">Breaking change: FailTestOnLeakRunListener deleted<a class="headerlink" href="#breaking-change-failtestonleakrunlistener-deleted" title="Permanent link">¶</a></h3> |
| <p><code>FailTestOnLeakRunListener</code>, <code>FailTestOnLeak</code> and <code>FailAnnotatedTestOnLeakRunListener</code> were deprecated in LeakCanary 2.8 as they rely on hacking the Android Test library internals which have since changed, and have been replaced by <code>LeakAssertions.assertNoLeak()</code> and the <code>DetectLeaksAfterTestSuccess</code> test rule. I was initially planning of keep these around, but as I tried to increase API level coverage in LeakCanary I needed to upgrade the Android Test library to a more recent version, and the hacks now had compilation errors. So they’re gone: <a href="https://github.com/square/leakcanary/commit/7152d6e2f8bea866e3bd5397b882d5098bed7d8b">#2282</a>. If you can’t use the test rules just yet, you’re welcome to copy paste the listener implementations in your own codebase.</p> |
| <h3 id="other-bug-fixes-and-improvements_2">Other bug fixes and improvements 🐛🔨<a class="headerlink" href="#other-bug-fixes-and-improvements_2" title="Permanent link">¶</a></h3> |
| <ul> |
| <li>💥 <a href="https://github.com/square/leakcanary/pull/2367">#2367</a> Fixed <code>AndroidLeakFixes.FLUSH_HANDLER_THREADS</code> (<code>HandlerThread</code> can have a null <code>Looper</code>).</li> |
| <li>💥 <a href="https://github.com/square/leakcanary/issues/2286">#2286</a> Update Curtains to include Proguard rules and prevent <code>WindowCallbackWrapper</code> crashes.</li> |
| <li>💥 <a href="https://github.com/square/leakcanary/issues/2294">#2294</a> Fixed <code>WindowDelegateCallback.onMenuOpened()</code> crash.</li> |
| <li>🐤 <a href="https://github.com/square/leakcanary/pull/2328">#2328</a> Fixed ToastEventListener leak. Sorry 😬!</li> |
| <li>💥 <a href="https://github.com/square/leakcanary/issues/2310">#2310</a> Fixed crash when using WorkManager < 2.1.0.</li> |
| <li>💥 <a href="https://github.com/square/leakcanary/issues/2342">#2342</a> Fixed crash when <code>HashSet.map</code> is null (which isn’t supposed to happen, oh well, Android 🤷♂️).</li> |
| <li>🐛 <a href="https://github.com/square/leakcanary/issues/2117">#2117</a> Fixed StrictMode disk read violations.</li> |
| <li>💥 <a href="https://github.com/square/leakcanary/pull/2351">#2351</a> Fixed a race causing a startup crash.</li> |
| <li>💥 <a href="https://github.com/square/leakcanary/issues/2315">#2315</a> Fixed crash when using Okio 1.14.</li> |
| <li>🐛 <a href="https://github.com/square/leakcanary/issues/2182">#2182</a> Fixed multi rescheduling of <code>BackgroundListener$checkAppInBackground</code>.</li> |
| <li>💥 <a href="https://github.com/square/leakcanary/issues/2360">#2360</a> Fixed SQLiteOpenHelper concurrent creation crash.</li> |
| </ul> |
| <p>This list reflects only a subset of all changes. For more details, see the <a href="https://github.com/square/leakcanary/milestone/23">2.9 Milestone</a> and the <a href="https://github.com/square/leakcanary/compare/v2.8.1...v2.9.1">full diff</a>.</p> |
| <h2 id="version-281-2022-01-06">Version 2.8.1 (2022-01-06)<a class="headerlink" href="#version-281-2022-01-06" title="Permanent link">¶</a></h2> |
| <p>This is a bugfix release, a quick follow up to <code>2.8</code> which had a few major issues 😅. If you haven’t yet, you should definitely read the <code>2.8</code> changelog.</p> |
| <h3 id="thanks">Thanks<a class="headerlink" href="#thanks" title="Permanent link">¶</a></h3> |
| <p>Please thank |
| <a href="https://github.com/dicosta">@dicosta</a>, |
| <a href="https://github.com/Goooler">@Goooler</a>, |
| <a href="https://github.com/plnice">@plnice</a>, |
| <a href="https://github.com/preetha1326">@preetha1326</a> |
| for their contributions, bug reports and feature requests 🙏 🙏 🙏.</p> |
| <h3 id="crash-fixes">Crash fixes 💥💥💥<a class="headerlink" href="#crash-fixes" title="Permanent link">¶</a></h3> |
| <p>This patch release fixes not 1, not 2, but 3 crashes!</p> |
| <ul> |
| <li>💥 <a href="https://github.com/square/leakcanary/pull/2268">#2268</a> WorkManager expedited request crashes before API 31.</li> |
| <li>💥 <a href="https://github.com/square/leakcanary/issues/2270">#2270</a> Updating <code>LeakCanary.config</code> crashes when <code>AppWatcher</code> is not installed.</li> |
| <li>💥 <a href="https://github.com/square/leakcanary/issues/2271">#2271</a> Analysis failure on API 25 because <code>HashMap$Entry</code> became <code>HashMap$HashMapEntry</code> (on API 25) before it finally changed to <code>HashMap$Node</code>.</li> |
| </ul> |
| <p>For more details, see the <a href="https://github.com/square/leakcanary/milestone/24">2.8.1 Milestone</a> and the <a href="https://github.com/square/leakcanary/compare/v2.8...v2.8.1">full diff</a>.</p> |
| <h2 id="version-28-2022-01-04">Version 2.8 (2022-01-04)<a class="headerlink" href="#version-28-2022-01-04" title="Permanent link">¶</a></h2> |
| <p>Note: please update to <code>2.8.1</code> instead.</p> |
| <h3 id="preface_1">Preface<a class="headerlink" href="#preface_1" title="Permanent link">¶</a></h3> |
| <p>The last release was 9 months ago. What happened?! Well, soon after releasing LeakCanary 2.7, I had my 2<sup>nd</sup> baby, a wonderful daughter 😍. Having 2 young kids leaves a lot less time available for Open Source work… but it’s worth it!</p> |
| <p>― <a href="https://twitter.com/Piwai">P.Y.</a></p> |
| <h3 id="thanks_1">Thanks<a class="headerlink" href="#thanks_1" title="Permanent link">¶</a></h3> |
| <p>Please thank |
| <a href="https://github.com/aaronweihe">@aaronweihe</a>, |
| <a href="https://github.com/alhah">@alhah</a>, |
| <a href="https://github.com/Andre-max">@Andre-max</a>, |
| <a href="https://github.com/AoraMD">@AoraMD</a>, |
| <a href="https://github.com/BraisGabin">@BraisGabin</a>, |
| <a href="https://github.com/breezenan">@breezenan</a>, |
| <a href="https://github.com/Goooler">@Goooler</a>, |
| <a href="https://github.com/iliaskomp">@iliaskomp</a> |
| <a href="https://github.com/Jeff11">@Jeff11</a>, |
| <a href="https://github.com/jmnwong">@jmnwong</a>, |
| <a href="https://github.com/IdioticMadman">@IdioticMadman</a>, |
| <a href="https://github.com/keyur1sst">@keyur1sst</a>, |
| <a href="https://github.com/lchen8">@lchen8</a>, |
| <a href="https://github.com/leinardi">@leinardi</a>, |
| <a href="https://github.com/Maragues">@Maragues</a>, |
| <a href="https://github.com/mars885">@mars885</a>, |
| <a href="https://github.com/mateuszkwiecinski">@mateuszkwiecinski</a>, |
| <a href="https://github.com/matiash">@matiash</a>, |
| <a href="https://github.com/maxxx">@maxxx</a>, |
| <a href="https://github.com/preetha1326">@preetha1326</a>, |
| <a href="https://github.com/SimonMarquis">@SimonMarquis</a>, |
| <a href="https://github.com/slavonnet">@slavonnet</a>, |
| <a href="https://github.com/Sonphil">@Sonphil</a>, |
| <a href="https://github.com/summerlyr">@summerlyr</a>, |
| <a href="https://github.com/SUPERCILEX">@SUPERCILEX</a>, |
| <a href="https://github.com/utwyko">@utwyko</a>, |
| <a href="https://github.com/ZacSweers">@ZacSweers</a>, |
| <a href="https://github.com/ziranshang">@ziranshang</a>, |
| <a href="https://github.com/zoltish">@zoltish</a> |
| for their contributions, bug reports and feature requests 🙏 🙏 🙏.</p> |
| <h3 id="improved-support-for-data-structure-internals">Improved support for data structure internals<a class="headerlink" href="#improved-support-for-data-structure-internals" title="Permanent link">¶</a></h3> |
| <p>🤓 Inspired <a href="https://twitter.com/RalucaSauciuc/status/1343800565352996871">by Android Studio</a>, LeakCanary’s node discovery during heap graph traversal is now abstracted away. This allows overlaying logical structure over common data structure internals.</p> |
| <p>😅 WHAT?!</p> |
| <p>👉 This means we can make known data structures look more like their APIs than their internals. For example, developers tend to think of setting a <code>HashMap</code> entry as <code>map["key"] = value</code> rather than <code>map.table[hash("key")].next.next.next = Node(value)</code>, which is what LeakCanary would previously show in its leak traces.</p> |
| <p>Let’s look at a <code>HashMap</code> example:</p> |
| <div class="highlight"><pre><span></span><code><span class="kd">class</span><span class="w"> </span><span class="nc">CheckoutController</span><span class="w"> </span><span class="p">{</span> |
| |
| <span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">tabs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">HashMap</span><span class="o"><</span><span class="kt">String</span><span class="p">,</span><span class="w"> </span><span class="n">Tab</span><span class="o">></span><span class="p">()</span> |
| |
| <span class="w"> </span><span class="kd">fun</span><span class="w"> </span><span class="nf">addItemsTab</span><span class="p">(</span><span class="n">tab</span><span class="p">:</span><span class="w"> </span><span class="n">Tab</span><span class="p">)</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="n">tabs</span><span class="o">[</span><span class="s">"ItemsTab"</span><span class="o">]</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">tab</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="p">}</span> |
| </code></pre></div> |
| <p>If the <code>Tab</code> instance holds on to a view, we might see a leak trace that would look like this:</p> |
| <div class="highlight"><pre><span></span><code>│ ... |
| ├─ com.example.CheckoutController instance |
| │ ↓ CheckoutController.tabs |
| ├─ java.util.HashMap instance |
| │ ↓ HashMap.table |
| ├─ java.util.HashMap$Node[] array |
| │ ↓ HashMap$Node[42] |
| ├─ java.util.HashMap$Node instance |
| │ ↓ HashMap$Node.next |
| ├─ java.util.HashMap$Node instance |
| │ ↓ HashMap$Node.value |
| ├─ com.example.Tab instance |
| │ ... |
| </code></pre></div> |
| <p>With the improved data structure support, the leak trace is much clearer (also note how the <code>ItemsTab</code> string key is now surfaced):</p> |
| <div class="highlight"><pre><span></span><code>│ ... |
| ├─ com.example.CheckoutController instance |
| │ ↓ CheckoutController.tabs |
| ├─ java.util.HashMap instance |
| │ ↓ HashMap[ItemsTab] |
| ├─ com.example.Tab instance |
| │ ... |
| </code></pre></div> |
| <p>Another benefit of this change is that leak signatures become less dependent of the runtime, and therefore are more consistent. This is especially true for any data structure that relies on a linked list (<code>HashMap</code>, <code>LinkedList</code>, <code>MessageQueue</code>, …). Currently LeakCanary supports a limited set of common data structures from Apache Harmony, Open JDK, and the Android SDK. Let me know what else you need!</p> |
| <h3 id="objectanimator-leaks">ObjectAnimator leaks<a class="headerlink" href="#objectanimator-leaks" title="Permanent link">¶</a></h3> |
| <p>LeakCanary will now detect leaks that trigger when forgetting to cancel <code>ObjectAnimator</code>. This new feature is enabled by the node discovery changes described above!</p> |
| <p>Let’s say you accidentally start an infinite <code>ObjectAnimator</code> and never cancel it, like so:</p> |
| <div class="highlight"><pre><span></span><code><span class="kd">class</span><span class="w"> </span><span class="nc">ExampleActivity</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="n">Activity</span><span class="p">()</span><span class="w"> </span><span class="p">{</span> |
| |
| <span class="w"> </span><span class="kd">override</span><span class="w"> </span><span class="kd">fun</span><span class="w"> </span><span class="nf">onCreate</span><span class="p">(</span><span class="n">savedInstanceState</span><span class="p">:</span><span class="w"> </span><span class="n">Bundle?)</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="k">super</span><span class="p">.</span><span class="na">onCreate</span><span class="p">(</span><span class="n">savedInstanceState</span><span class="p">)</span> |
| <span class="w"> </span><span class="n">setContentView</span><span class="p">(</span><span class="n">R</span><span class="p">.</span><span class="na">layout</span><span class="p">.</span><span class="na">main_activity</span><span class="p">)</span> |
| <span class="w"> </span><span class="n">findViewById</span><span class="o"><</span><span class="n">Button</span><span class="o">></span><span class="p">(</span><span class="n">R</span><span class="p">.</span><span class="na">id</span><span class="p">.</span><span class="na">button</span><span class="p">).</span><span class="na">setOnClickListener</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">view</span><span class="w"> </span><span class="o">-></span> |
| <span class="w"> </span><span class="n">ObjectAnimator</span><span class="p">.</span><span class="na">ofFloat</span><span class="p">(</span><span class="n">view</span><span class="p">,</span><span class="w"> </span><span class="n">View</span><span class="p">.</span><span class="na">ALPHA</span><span class="p">,</span><span class="w"> </span><span class="m">0.1f</span><span class="p">,</span><span class="w"> </span><span class="m">0.2f</span><span class="p">).</span><span class="na">apply</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="n">duration</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="m">100</span> |
| <span class="w"> </span><span class="n">repeatMode</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ValueAnimator</span><span class="p">.</span><span class="na">REVERSE</span> |
| <span class="w"> </span><span class="n">repeatCount</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ValueAnimator</span><span class="p">.</span><span class="na">INFINITE</span> |
| <span class="w"> </span><span class="n">start</span><span class="p">()</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="p">}</span> |
| </code></pre></div> |
| <p>In previous releases, LeakCanary would detect that the animated view is leaking but it wouldn’t be able to find the leak and instead would report it as an unreachable object: <em>An unreachable object is still in memory but LeakCanary could not find a strong reference path from GC roots.</em></p> |
| <p>LeakCanary now reports the leak and adds animator state information, helping detect and fix any infinite <code>ObjectAnimator</code>.</p> |
| <div class="highlight"><pre><span></span><code>┬─── |
| │ GC Root: Thread object |
| │ |
| ├─ java.lang.Thread instance |
| │ Leaking: NO (the main thread always runs) |
| │ Thread name: 'main' |
| │ ↓ Thread.threadLocals |
| │ ~~~~~~~~~~~~ |
| ... |
| ├─ android.animation.ObjectAnimator instance |
| │ Leaking: UNKNOWN |
| │ mListeners = null |
| │ mPropertyName = null |
| │ mProperty.mName = alpha |
| │ mProperty.mType = java.lang.Float |
| │ mInitialized = true |
| │ mStarted = true |
| │ mRunning = true |
| │ mAnimationEndRequested = false |
| │ mDuration = 100 |
| │ mStartDelay = 0 |
| │ mRepeatCount = INFINITE (-1) |
| │ mRepeatMode = REVERSE (2) |
| │ ↓ ObjectAnimator.mTarget |
| │ ~~~~~~~ |
| ╰→ android.widget.Button instance |
| Leaking: YES (View.mContext references a destroyed activity) |
| </code></pre></div> |
| <p>To learn more, see this AOSP issue: <a href="https://issuetracker.google.com/issues/212993949">ObjectAnimator.mTarget weak ref creates memory leaks on infinite animators</a>.</p> |
| <h3 id="leak-detection-in-tests">Leak detection in tests<a class="headerlink" href="#leak-detection-in-tests" title="Permanent link">¶</a></h3> |
| <p>Previous releases of <code>leakcanary-android-instrumentation</code> introduced a <code>FailTestOnLeakRunListener</code> which could run leak detection after each UI tests. Unfortunately <code>FailTestOnLeakRunListener</code> relied on a hack around <code>androidx.test</code> internals to report failures. The internals keep changing with every <code>androidx.test</code> release and breaking <code>FailTestOnLeakRunListener</code> 😭.</p> |
| <p><code>FailTestOnLeakRunListener</code> is now deprecated (👋) and replaced by the <code>DetectLeaksAfterTestSuccess</code> test rule, which you can add to your test like any normal test rule.</p> |
| <p>Additionally, you can call <code>LeakAssertions.assertNoLeak()</code> from anywhere in your instrumentation tests. You can also annotate tests with <code>@SkipLeakDetection</code> (for that to work you’ll also need to set up the <code>TestDescriptionHolder</code> test rule).</p> |
| <div class="highlight"><pre><span></span><code><span class="kd">class</span><span class="w"> </span><span class="nc">CartTest</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="nd">@get</span><span class="p">:</span><span class="n">Rule</span> |
| <span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">rules</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">RuleChain</span><span class="p">.</span><span class="na">outerRule</span><span class="p">(</span><span class="n">TestDescriptionHolder</span><span class="p">)</span> |
| <span class="w"> </span><span class="p">.</span><span class="na">around</span><span class="p">(</span><span class="n">DetectLeaksAfterTestSuccess</span><span class="p">())</span> |
| <span class="w"> </span><span class="p">.</span><span class="na">around</span><span class="p">(</span><span class="n">ActivityScenarioRule</span><span class="p">(</span><span class="n">CartActivity</span><span class="o">::</span><span class="n">class</span><span class="p">.</span><span class="na">java</span><span class="p">))</span> |
| |
| <span class="w"> </span><span class="nd">@Test</span> |
| <span class="w"> </span><span class="kd">fun</span><span class="w"> </span><span class="nf">addItemToCart</span><span class="p">()</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="c1">// ...</span> |
| <span class="w"> </span><span class="p">}</span> |
| |
| <span class="w"> </span><span class="nd">@SkipLeakDetection</span><span class="p">(</span><span class="s">"See #1234"</span><span class="p">)</span> |
| <span class="w"> </span><span class="nd">@Test</span> |
| <span class="w"> </span><span class="kd">fun</span><span class="w"> </span><span class="nf">removeItemFromCart</span><span class="p">()</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="c1">// ...</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="p">}</span> |
| </code></pre></div> |
| <h3 id="android-12">Android 12<a class="headerlink" href="#android-12" title="Permanent link">¶</a></h3> |
| <p>Hopefully this time we fixed everything that Android 12 broke: missing <code>exported:true</code> tags, missing pending intent flags, and <code>ForegroundServiceStartNotAllowedException</code> crashes. If not, let us know! Can’t wait for Android 13 to break everything again 🤬.</p> |
| <h3 id="workmanager">WorkManager<a class="headerlink" href="#workmanager" title="Permanent link">¶</a></h3> |
| <p>Running an Android Service without crashing (<code>ForegroundServiceStartNotAllowedException</code>…) is becoming harder with every release of Android, so I got rid of the LeakCanary heap analyzer service! Instead, LeakCanary leverages WorkManager if you already have it as a dependency. If you don’t use WorkManager, then LeakCanary will fall back to using a simple thread.</p> |
| <p>Note: I recommend using at least <a href="https://developer.android.com/jetpack/androidx/releases/work#2.7.0">WorkManager 2.7.0</a> as it adds the <code>WorkRequest.Builder.setExpedited()</code> API which LeakCanary leverages if available.</p> |
| <h3 id="multi-process">Multi process<a class="headerlink" href="#multi-process" title="Permanent link">¶</a></h3> |
| <p>Switching to WorkManager also impacts the LeakCanary multi process approach, which now leverages WorkManager remote jobs. Blog on how I got this working: <a href="https://py.hashnode.dev/workmanager-multi-process-for-libraries">WorkManager multi-process for libraries</a>.</p> |
| <p>Multi process is harder to get right so you should only use this if LeakCanary frequently runs out of memory while performing the heap analysis. Here are the updated set up steps:</p> |
| <p>1) Add the <code>leakcanary-android-process</code> dependency and <strong>keep the <code>leakcanary-android</code> dependency</strong>.</p> |
| <div class="highlight"><pre><span></span><code><span class="n">dependencies</span><span class="w"> </span><span class="o">{</span> |
| <span class="w"> </span><span class="n">debugImplementation</span><span class="w"> </span><span class="s1">'com.squareup.leakcanary:leakcanary-android:2.8'</span> |
| <span class="w"> </span><span class="n">debugImplementation</span><span class="w"> </span><span class="s1">'com.squareup.leakcanary:leakcanary-android-process:2.8'</span> |
| <span class="o">}</span> |
| </code></pre></div> |
| <p>2) Skip the initialization code in the <code>Application</code> class</p> |
| <div class="highlight"><pre><span></span><code><span class="kd">class</span><span class="w"> </span><span class="nc">ExampleApplication</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="n">Application</span><span class="p">()</span><span class="w"> </span><span class="p">{</span> |
| |
| <span class="w"> </span><span class="kd">override</span><span class="w"> </span><span class="kd">fun</span><span class="w"> </span><span class="nf">onCreate</span><span class="p">()</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">LeakCanaryProcess</span><span class="p">.</span><span class="na">isInAnalyzerProcess</span><span class="p">(</span><span class="k">this</span><span class="p">))</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="k">return</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="w"> </span><span class="k">super</span><span class="p">.</span><span class="na">onCreate</span><span class="p">()</span> |
| <span class="w"> </span><span class="c1">// normal init goes here, skipped in :leakcanary process.</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="p">}</span> |
| </code></pre></div> |
| <p>That’s it! Note that event listeners (see below) related to the analysis will fire in the remote process.</p> |
| <h3 id="androidx-app-startup">AndroidX App Startup<a class="headerlink" href="#androidx-app-startup" title="Permanent link">¶</a></h3> |
| <p>LeakCanary now optionally supports the <a href="https://developer.android.com/topic/libraries/app-startup">AndroidX App Startup library</a>. All you need to do is replace the <code>leakcanary-android</code> dependency with <code>leakcanary-android-startup</code>:</p> |
| <div class="highlight"><pre><span></span><code><span class="n">dependencies</span><span class="w"> </span><span class="o">{</span> |
| <span class="w"> </span><span class="c1">// Remove the normal leakcanary-android dependency</span> |
| <span class="w"> </span><span class="c1">// debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.8'</span> |
| <span class="w"> </span><span class="n">debugImplementation</span><span class="w"> </span><span class="s1">'com.squareup.leakcanary:leakcanary-android-startup:2.8'</span> |
| <span class="o">}</span> |
| </code></pre></div> |
| <p>Note 1: <code>leakcanary-android</code> adds the code for automatic installl to <code>leakcanary-android-core</code>. If you’re calling <code>AppWatcher.manualInstall()</code>, you can depend directly on <code>leakcanary-android-core</code> instead of <code>leakcanary-android</code>, and you won’t need the disable any automatic install.</p> |
| <p>Note 2: the same principle applies to <code>leakcanary-object-watcher-android</code>: it depends on <code>leakcanary-object-watcher-android-core</code> and adds automatic install, while <code>leakcanary-object-watcher-android-startup</code> leverages the App Startup library. Same for <code>plumber-android</code>, <code>plumber-android-core</code> and <code>plumber-android-startup</code>.</p> |
| <h3 id="event-listeners">Event listeners<a class="headerlink" href="#event-listeners" title="Permanent link">¶</a></h3> |
| <p><code>LeakCanary.Config</code> has a new <code>eventListeners</code> field allowing you to react to LeakCanary’s lifecycle. If you want to customize this, you most likely should be keeping the default list of listeners and add or remove from it.</p> |
| <p>For example, if you want to disable the LeakCanary toast:</p> |
| <div class="highlight"><pre><span></span><code><span class="n">LeakCanary</span><span class="p">.</span><span class="na">config</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">LeakCanary</span><span class="p">.</span><span class="na">config</span><span class="p">.</span><span class="na">run</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="n">copy</span><span class="p">(</span> |
| <span class="w"> </span><span class="n">eventListeners</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">eventListeners</span><span class="p">.</span><span class="na">filter</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="nb">it</span><span class="w"> </span><span class="k">!is</span><span class="w"> </span><span class="n">ToastEventListener</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="w"> </span><span class="p">)</span> |
| <span class="p">}</span> |
| </code></pre></div> |
| <p>If you want to upload heap analysis results:</p> |
| <div class="highlight"><pre><span></span><code><span class="n">LeakCanary</span><span class="p">.</span><span class="na">config</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">LeakCanary</span><span class="p">.</span><span class="na">config</span><span class="p">.</span><span class="na">run</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="n">copy</span><span class="p">(</span> |
| <span class="w"> </span><span class="n">eventListeners</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">eventListeners</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">EventListener</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">event</span><span class="w"> </span><span class="o">-></span> |
| <span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">event</span><span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="n">HeapAnalysisSucceeded</span><span class="p">)</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="c1">// Upload event.heapAnalysis</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="w"> </span><span class="p">)</span> |
| <span class="p">}</span> |
| </code></pre></div> |
| <p>Note: <code>Leakcanary.Config.onHeapAnalyzedListener</code> still works but is now deprecated.</p> |
| <p>Feedback welcome on this new API!</p> |
| <h3 id="other-bug-fixes-and-improvements_3">Other bug fixes and improvements 🐛🔨<a class="headerlink" href="#other-bug-fixes-and-improvements_3" title="Permanent link">¶</a></h3> |
| <ul> |
| <li><a href="https://github.com/square/leakcanary/issues/2096">#2096</a> Opening / sharing heap dump files now supports LeakCanary as an option.</li> |
| <li><a href="https://github.com/square/leakcanary/issues/2210">#2210</a> First Compose dedicated object inspectors!</li> |
| <li><a href="https://github.com/square/leakcanary/pull/2121">#2121</a> Support for customizing the heap dumper.</li> |
| </ul> |
| <p>This list reflects only a subset of all changes. For more details, see the <a href="https://github.com/square/leakcanary/milestone/22">2.8 Milestone</a> and the <a href="https://github.com/square/leakcanary/compare/v2.7...v2.8">full diff</a>.</p> |
| <h2 id="version-27-2021-03-26">Version 2.7 (2021-03-26)<a class="headerlink" href="#version-27-2021-03-26" title="Permanent link">¶</a></h2> |
| <p>Please thank |
| <a href="https://github.com/chao2zhang">@chao2zhang</a>, |
| <a href="https://github.com/ihrupin">@ihrupin</a>, |
| <a href="https://github.com/jzbrooks">@jzbrooks</a>, |
| <a href="https://github.com/msfjarvis">@msfjarvis</a>, |
| <a href="https://github.com/reneargento">@reneargento</a>, |
| <a href="https://github.com/Unpublished">@Unpublished</a> |
| for their contributions, bug reports and feature requests 🙏 🙏 🙏.</p> |
| <h3 id="finer-grained-root-view-watching">Finer grained root view watching<a class="headerlink" href="#finer-grained-root-view-watching" title="Permanent link">¶</a></h3> |
| <p>In version 2.6, LeakCanary added detection of root views retained after <code>View.onDetachedFromWindow()</code>. This helps find more leaks, but unfortunately some Android widgets keep a detached root view around to reattach it later (e.g. spinner). App developers also sometimes do the same with dialogs, keeping a single instance around and calling <code>show()</code> and <code>hide()</code> as needed. As a result, LeakCanary would report leaks that were actually not leaks.</p> |
| <p>In version 2.7, the default behavior changed: LeakCanary will continue to detect leaks of toasts, but will ignore root views created by a PopupWindow (which is what Android widgets use). It will also ignore root views created by a dialog by default, and you can turn this back on by setting the <code>leak_canary_watcher_watch_dismissed_dialogs</code> resource boolean to true:</p> |
| <div class="highlight"><pre><span></span><code><span class="cp"><?xml version="1.0" encoding="utf-8"?></span> |
| <span class="nt"><resources></span> |
| <span class="w"> </span><span class="nt"><bool</span><span class="w"> </span><span class="na">name=</span><span class="s">"leak_canary_watcher_watch_dismissed_dialogs"</span><span class="nt">></span>true<span class="nt"></bool></span> |
| <span class="nt"></resources></span> |
| </code></pre></div> |
| <p>This is implemented using a new Square library: <a href="https://github.com/square/curtains">Curtains</a>.</p> |
| <h3 id="targeting-android-12">Targeting Android 12<a class="headerlink" href="#targeting-android-12" title="Permanent link">¶</a></h3> |
| <p>We fixed two issues for apps that want to target Android 12:</p> |
| <ul> |
| <li><a href="https://github.com/square/leakcanary/pull/2074">#2074</a> Activities that use intent filters must declare the <code>android:exported</code> attribute.</li> |
| <li><a href="https://github.com/square/leakcanary/issues/2079">#2079</a> PendingIntent requires the <code>FLAG_IMMUTABLE</code> flag.</li> |
| </ul> |
| <h3 id="bug-fixes-and-improvements">Bug fixes and improvements 🐛🔨<a class="headerlink" href="#bug-fixes-and-improvements" title="Permanent link">¶</a></h3> |
| <ul> |
| <li><a href="https://github.com/square/leakcanary/issues/2075">#2075</a> Fixed crash when sharing heap dumps.</li> |
| <li><a href="https://github.com/square/leakcanary/issues/2067">#2067</a> Fixed crash when opening leaks from older versions (before 2.6) of LeakCanary.</li> |
| <li><a href="https://github.com/square/leakcanary/issues/2049">#2049</a> Fixed Plumber crash due to R8 shaking AndroidLeakFixes.</li> |
| <li><a href="https://github.com/square/leakcanary/issues/2084">#2084</a> Fixed Shark crash when used from multiple threads.</li> |
| <li><a href="https://github.com/square/leakcanary/issues/2054">#2054</a> 🙈🙉🙊 Blocked Monkeys from deleting leaks.</li> |
| <li><a href="https://github.com/square/leakcanary/issues/2069">#2069</a> Added X button to the root leak activity (for custom devices with no back button)</li> |
| <li><a href="https://github.com/square/leakcanary/issues/2091">#2091</a> Added receiver details if LoadedApk shows up in the leaktrace.</li> |
| <li><a href="https://github.com/square/leakcanary/issues/2083">#2083</a> Added service status details (created or not) to leaktrace.</li> |
| <li><a href="https://github.com/square/leakcanary/pull/2099">#2099</a> Retry button if analysis fails.</li> |
| <li><a href="https://github.com/square/leakcanary/pull/2066">#2066</a> When heap analysis in UI tests is skipped and NoAnalysis is returned, NoAnalysis now includes a reason to help debug why it didn’t run.</li> |
| <li><a href="https://github.com/square/leakcanary/issues/2000">#2000</a> The LeakCanary CI now leverages GitHub actions instead of Travis.</li> |
| </ul> |
| <p>For more details, see the <a href="https://github.com/square/leakcanary/milestone/21">2.7 Milestone</a> and the <a href="https://github.com/square/leakcanary/compare/v2.6...v2.7">full diff</a>.</p> |
| <h2 id="version-26-christmas-release-2020-12-24">Version 2.6 - Christmas Release 🎄 (2020-12-24)<a class="headerlink" href="#version-26-christmas-release-2020-12-24" title="Permanent link">¶</a></h2> |
| <p>Please thank |
| <a href="https://github.com/chao2zhang">@chao2zhang</a>, |
| <a href="https://github.com/ChaosLeung">@ChaosLeung</a>, |
| <a href="https://github.com/LitterSun">@LitterSun</a>, |
| <a href="https://github.com/mickverm">@mickverm</a>, |
| <a href="https://github.com/opatry">@opatry</a>, |
| <a href="https://github.com/Thomas-Vos">@Thomas-Vos</a>, |
| <a href="https://github.com/tricknology">@tricknology</a>, |
| <a href="https://github.com/rahul-a">@rahul-a</a>, |
| <a href="https://github.com/samoylenkodmitry">@samoylenkodmitry</a>, |
| <a href="https://github.com/sing0055">@sing0055</a>, |
| <a href="https://github.com/ubiratansoares">@ubiratansoares</a> |
| for their contributions, bug reports and feature requests 🙏 🙏 🙏.</p> |
| <p>This Christmas Release includes several external contributions and a bunch of cool new features! 🎁🎁</p> |
| <h3 id="detecting-root-views-retained-after-viewondetachedfromwindow">Detecting root views retained after <code>View.onDetachedFromWindow()</code><a class="headerlink" href="#detecting-root-views-retained-after-viewondetachedfromwindow" title="Permanent link">¶</a></h3> |
| <p>On Android, every displayed view hierarchy is attached to a window, whether it be the view hierarchy of an activity, a dialog, a toast or <a href="http://www.piwai.info/chatheads-basics">a chat head</a>. After a view hierarchy is detached from its window, it should be garbage collected.</p> |
| <p>LeakCanary already detects leaks of activity view hierarchies because retained detached views reference their activity context and LeakCanary detects activities retained after <code>Activity.onDestroy()</code>. In this new release, LeakCanary will now detect the leak of a dialog view hierarchy as soon as that dialog is dismissed, or any other view that is passed to <a href="https://developer.android.com/reference/android/view/ViewManager#removeView(android.view.View)">WindowManager.removeView()</a>.</p> |
| <h3 id="detecting-services-retained-after-serviceondestroy">Detecting services retained after <code>Service.onDestroy()</code><a class="headerlink" href="#detecting-services-retained-after-serviceondestroy" title="Permanent link">¶</a></h3> |
| <p>After an Android <a href="https://developer.android.com/reference/android/app/Service">service</a> is destroyed, it should be garbage collected. Unfortunately, the Android SDK does not provide any generic API to observe the service lifecycle. We worked around that using reflection on greylist APIs (details in <a href="https://github.com/square/leakcanary/pull/2014">#2014</a>). Let’s hope this motivates the Android team to <a href="https://twitter.com/Piwai/status/1342029560116891648">build the APIs developers need</a>.</p> |
| <h3 id="configuring-retained-object-detection">Configuring retained object detection<a class="headerlink" href="#configuring-retained-object-detection" title="Permanent link">¶</a></h3> |
| <p>With the detection of 2 new types of retained objects, we’re also adding APIs to configure which <em>watchers</em> should be installed as well as adding filtering capabilities.</p> |
| <p>First, disable the automatic install:</p> |
| <div class="highlight"><pre><span></span><code><span class="cp"><?xml version="1.0" encoding="utf-8"?></span> |
| <span class="nt"><resources></span> |
| <span class="w"> </span><span class="nt"><bool</span><span class="w"> </span><span class="na">name=</span><span class="s">"leak_canary_watcher_auto_install"</span><span class="nt">></span>false<span class="nt"></bool></span> |
| <span class="nt"></resources></span> |
| </code></pre></div> |
| <p>Then you can install LeakCanary manually. LeakCanary 2.6 comes with 4 watchers installed by default: <code>ActivityWatcher</code>, <code>FragmentAndViewModelWatcher</code>, <code>RootViewWatcher</code>, <code>ServiceWatcher</code>. Here’s an example to get all the default watchers except <code>ServiceWatcher</code>:</p> |
| <div class="highlight"><pre><span></span><code><span class="kd">class</span><span class="w"> </span><span class="nc">DebugExampleApplication</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="n">ExampleApplication</span><span class="p">()</span><span class="w"> </span><span class="p">{</span> |
| |
| <span class="w"> </span><span class="kd">override</span><span class="w"> </span><span class="kd">fun</span><span class="w"> </span><span class="nf">onCreate</span><span class="p">()</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="k">super</span><span class="p">.</span><span class="na">onCreate</span><span class="p">()</span> |
| |
| <span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">watchersToInstall</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">AppWatcher</span><span class="p">.</span><span class="na">appDefaultWatchers</span><span class="p">(</span><span class="n">application</span><span class="p">)</span> |
| <span class="w"> </span><span class="p">.</span><span class="na">filter</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nb">it</span><span class="w"> </span><span class="k">!is</span><span class="w"> </span><span class="n">ServiceWatcher</span><span class="w"> </span><span class="p">}</span> |
| |
| <span class="w"> </span><span class="n">AppWatcher</span><span class="p">.</span><span class="na">manualInstall</span><span class="p">(</span> |
| <span class="w"> </span><span class="n">application</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">application</span><span class="p">,</span> |
| <span class="w"> </span><span class="n">watchersToInstall</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">watchersToInstall</span> |
| <span class="w"> </span><span class="p">)</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="p">}</span> |
| </code></pre></div> |
| <p>LeakCanary introduces a new functional (SAM) interface implemented by <code>ObjectWatcher</code>: <code>ReachabilityWatcher</code>, with a <code>ReachabilityWatcher.expectWeaklyReachable()</code> method that replaces the now deprecated <code>ObjectWatcher.watch()</code> method. You can create the default watcher instances with a custom <code>ReachabilityWatcher</code> that delegates to <code>AppWatcher.objectWatcher</code> but filters out specific instances (e.g. <code>BadSdkLeakingFragment</code>):</p> |
| <div class="highlight"><pre><span></span><code><span class="kd">class</span><span class="w"> </span><span class="nc">DebugExampleApplication</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="n">ExampleApplication</span><span class="p">()</span><span class="w"> </span><span class="p">{</span> |
| |
| <span class="w"> </span><span class="kd">override</span><span class="w"> </span><span class="kd">fun</span><span class="w"> </span><span class="nf">onCreate</span><span class="p">()</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="k">super</span><span class="p">.</span><span class="na">onCreate</span><span class="p">()</span> |
| |
| <span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">delegate</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">ReachabilityWatcher</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">watchedObject</span><span class="p">,</span><span class="w"> </span><span class="n">description</span><span class="w"> </span><span class="o">-></span> |
| <span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">watchedObject</span><span class="w"> </span><span class="k">!is</span><span class="w"> </span><span class="n">BadSdkLeakingFragment</span><span class="p">)</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="n">AppWatcher</span><span class="p">.</span><span class="na">objectWatcher</span><span class="p">.</span><span class="na">expectWeaklyReachable</span><span class="p">(</span><span class="n">watchedObject</span><span class="p">,</span><span class="w"> </span><span class="n">description</span><span class="p">)</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="w"> </span><span class="p">}</span> |
| |
| <span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">watchersToInstall</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">AppWatcher</span><span class="p">.</span><span class="na">appDefaultWatchers</span><span class="p">(</span><span class="n">application</span><span class="p">,</span><span class="w"> </span><span class="n">delegate</span><span class="p">)</span> |
| |
| <span class="w"> </span><span class="n">AppWatcher</span><span class="p">.</span><span class="na">manualInstall</span><span class="p">(</span> |
| <span class="w"> </span><span class="n">application</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">application</span><span class="p">,</span> |
| <span class="w"> </span><span class="n">watchersToInstall</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">watchersToInstall</span> |
| <span class="w"> </span><span class="p">)</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="p">}</span> |
| </code></pre></div> |
| <p>With these new configuration options, <code>AppWatcher.config</code> is now deprecated and a no-op.</p> |
| <h3 id="dumping-the-heap-on-screen-off">Dumping the heap on screen off<a class="headerlink" href="#dumping-the-heap-on-screen-off" title="Permanent link">¶</a></h3> |
| <p>The default threshold to dump the heap is <strong>5 retained objects</strong> when the app is <strong>visible</strong>, and <strong>1 retained object</strong> when the app is <strong>not visible</strong>. Up until now, visible meant “the app has at least one activity in <strong>started</strong> state”. In LeakCanary 2.6, the app will now be considered <strong>not visible</strong> if the device screen is <strong>off</strong>, lowering the threshold to trigger heap dumps when you turn off the device screen.</p> |
| <h3 id="leakcanary-for-releases">LeakCanary for releases<a class="headerlink" href="#leakcanary-for-releases" title="Permanent link">¶</a></h3> |
| <p>LeakCanary 2.6 introduces a new artifact: <code>leakcanary-android-release</code>. This artifact exposes APIs to run a heap analysis in release builds, in production.</p> |
| <div class="admonition danger"> |
| <p class="admonition-title">Danger</p> |
| <p>Everything about this is experimental. Running a heap analysis in production is not a very common thing to do, and we’re still learning and experimenting with this. Also, both the artifact name and the APIs may change.</p> |
| </div> |
| <div class="highlight"><pre><span></span><code><span class="n">dependencies</span><span class="w"> </span><span class="o">{</span> |
| <span class="w"> </span><span class="c1">// debugImplementation because LeakCanary should only run in debug builds.</span> |
| <span class="w"> </span><span class="n">debugImplementation</span><span class="w"> </span><span class="s1">'com.squareup.leakcanary:leakcanary-android:2.6'</span> |
| |
| <span class="w"> </span><span class="c1">// NEW: LeakCanary for releases!</span> |
| <span class="w"> </span><span class="n">releaseImplementation</span><span class="w"> </span><span class="s1">'com.squareup.leakcanary:leakcanary-android-release:2.6'</span> |
| <span class="w"> </span><span class="c1">// Optional: detect retained objects. This helps but is not required.</span> |
| <span class="w"> </span><span class="n">releaseImplementation</span><span class="w"> </span><span class="s1">'com.squareup.leakcanary:leakcanary-object-watcher-android:2.6'</span> |
| <span class="o">}</span> |
| </code></pre></div> |
| <p>Here’s a code example that runs a heap analysis when the screen is turned off or the app enters background, checking first if a <a href="https://firebase.google.com/products/remote-config">Firebase Remote Config</a> flag is turned on, and uploading the result to Bugsnag:</p> |
| <div class="highlight"><pre><span></span><code><span class="kd">class</span><span class="w"> </span><span class="nc">ReleaseExampleApplication</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="n">ExampleApplication</span><span class="p">()</span><span class="w"> </span><span class="p">{</span> |
| |
| <span class="w"> </span><span class="c1">// Cancels heap analysis if "heap_analysis_flag" is false.</span> |
| <span class="w"> </span><span class="kd">private</span><span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">flagInterceptor</span><span class="w"> </span><span class="k">by</span><span class="w"> </span><span class="n">lazy</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="k">object</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="nc">HeapAnalysisInterceptor</span><span class="w"> </span><span class="p">{</span> |
| |
| <span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">remoteConfig</span><span class="p">:</span><span class="w"> </span><span class="n">FirebaseRemoteConfig</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">TODO</span><span class="p">()</span> |
| |
| <span class="w"> </span><span class="kd">override</span><span class="w"> </span><span class="kd">fun</span><span class="w"> </span><span class="nf">intercept</span><span class="p">(</span><span class="n">chain</span><span class="p">:</span><span class="w"> </span><span class="n">Chain</span><span class="p">):</span><span class="w"> </span><span class="n">HeapAnalysisJob</span><span class="p">.</span><span class="na">Result</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">remoteConfig</span><span class="p">.</span><span class="na">getBoolean</span><span class="p">(</span><span class="s">"heap_analysis_flag"</span><span class="p">))</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="n">chain</span><span class="p">.</span><span class="na">job</span><span class="p">.</span><span class="na">cancel</span><span class="p">(</span><span class="s">"heap_analysis_flag false"</span><span class="p">)</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">chain</span><span class="p">.</span><span class="na">proceed</span><span class="p">()</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="w"> </span><span class="p">}</span> |
| |
| <span class="w"> </span><span class="kd">private</span><span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">analysisClient</span><span class="w"> </span><span class="k">by</span><span class="w"> </span><span class="n">lazy</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="n">HeapAnalysisClient</span><span class="p">(</span> |
| <span class="w"> </span><span class="c1">// Use private app storage. cacheDir is never backed up which is important.</span> |
| <span class="w"> </span><span class="n">heapDumpDirectoryProvider</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">cacheDir</span><span class="w"> </span><span class="p">},</span> |
| <span class="w"> </span><span class="c1">// stripHeapDump: remove all user data from hprof before analysis.</span> |
| <span class="w"> </span><span class="n">config</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">HeapAnalysisConfig</span><span class="p">(</span><span class="n">stripHeapDump</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">true</span><span class="p">),</span> |
| <span class="w"> </span><span class="c1">// Default interceptors may cancel analysis for several other reasons.</span> |
| <span class="w"> </span><span class="n">interceptors</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">listOf</span><span class="p">(</span><span class="n">flagInterceptor</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">HeapAnalysisClient</span><span class="p">.</span><span class="na">defaultInterceptors</span><span class="p">(</span><span class="k">this</span><span class="p">)</span> |
| <span class="w"> </span><span class="p">)</span> |
| <span class="w"> </span><span class="p">}</span> |
| |
| <span class="w"> </span><span class="kd">private</span><span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">analysisExecutor</span><span class="w"> </span><span class="k">by</span><span class="w"> </span><span class="n">lazy</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="n">Executors</span><span class="p">.</span><span class="na">newSingleThreadExecutor</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="n">thread</span><span class="p">(</span><span class="n">start</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w"> </span><span class="n">name</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"Heap analysis executor"</span><span class="p">)</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="n">android</span><span class="p">.</span><span class="na">os</span><span class="p">.</span><span class="na">Process</span><span class="p">.</span><span class="na">setThreadPriority</span><span class="p">(</span><span class="n">THREAD_PRIORITY_BACKGROUND</span><span class="p">)</span> |
| <span class="w"> </span><span class="nb">it</span><span class="p">.</span><span class="na">run</span><span class="p">()</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="w"> </span><span class="p">}</span> |
| |
| <span class="w"> </span><span class="kd">private</span><span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">analysisCallback</span><span class="p">:</span><span class="w"> </span><span class="p">(</span><span class="n">Result</span><span class="p">)</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="kt">Unit</span><span class="w"> </span><span class="k">by</span><span class="w"> </span><span class="n">lazy</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">uploader</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">BugsnagHeapAnalysisUploader</span><span class="p">(</span><span class="k">this</span><span class="nd">@ReleaseExampleApplication</span><span class="p">)</span> |
| <span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">result</span><span class="w"> </span><span class="o">-></span> |
| <span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="p">(</span><span class="n">result</span><span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="n">Done</span><span class="p">)</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="n">uploader</span><span class="p">.</span><span class="na">upload</span><span class="p">(</span><span class="n">result</span><span class="p">.</span><span class="na">analysis</span><span class="p">)</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="w"> </span><span class="p">}</span> |
| |
| <span class="w"> </span><span class="kd">override</span><span class="w"> </span><span class="kd">fun</span><span class="w"> </span><span class="nf">onCreate</span><span class="p">()</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="k">super</span><span class="p">.</span><span class="na">onCreate</span><span class="p">()</span> |
| |
| <span class="w"> </span><span class="c1">// Delete any remaining heap dump (if we crashed)</span> |
| <span class="w"> </span><span class="n">analysisExecutor</span><span class="p">.</span><span class="na">execute</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="n">analysisClient</span><span class="p">.</span><span class="na">deleteHeapDumpFiles</span><span class="p">()</span> |
| <span class="w"> </span><span class="p">}</span> |
| |
| <span class="w"> </span><span class="c1">// Starts heap analysis on background importance</span> |
| <span class="w"> </span><span class="n">BackgroundTrigger</span><span class="p">(</span> |
| <span class="w"> </span><span class="n">application</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">,</span> |
| <span class="w"> </span><span class="n">analysisClient</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">analysisClient</span><span class="p">,</span> |
| <span class="w"> </span><span class="n">analysisExecutor</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">analysisExecutor</span><span class="p">,</span> |
| <span class="w"> </span><span class="n">analysisCallback</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">analysisCallback</span> |
| <span class="w"> </span><span class="p">).</span><span class="na">start</span><span class="p">()</span> |
| |
| <span class="w"> </span><span class="c1">// Starts heap analysis when screen off</span> |
| <span class="w"> </span><span class="n">ScreenOffTrigger</span><span class="p">(</span> |
| <span class="w"> </span><span class="n">application</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">this</span><span class="p">,</span> |
| <span class="w"> </span><span class="n">analysisClient</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">analysisClient</span><span class="p">,</span> |
| <span class="w"> </span><span class="n">analysisExecutor</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">analysisExecutor</span><span class="p">,</span> |
| <span class="w"> </span><span class="n">analysisCallback</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">analysisCallback</span> |
| <span class="w"> </span><span class="p">).</span><span class="na">start</span><span class="p">()</span> |
| <span class="w"> </span><span class="p">}</span> |
| |
| <span class="w"> </span><span class="cm">/**</span> |
| <span class="cm"> * Call this to trigger heap analysis manually, e.g. from</span> |
| <span class="cm"> * a help button.</span> |
| <span class="cm"> *</span> |
| <span class="cm"> * This method returns a `HeapAnalysisJob` on which you can</span> |
| <span class="cm"> * call `HeapAnalysisJob.cancel()` at any time.</span> |
| <span class="cm"> */</span> |
| <span class="w"> </span><span class="kd">fun</span><span class="w"> </span><span class="nf">triggerHeapAnalysisNow</span><span class="p">():</span><span class="w"> </span><span class="n">HeapAnalysisJob</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">job</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">analysisClient</span><span class="p">.</span><span class="na">newJob</span><span class="p">()</span> |
| <span class="w"> </span><span class="n">analysisExecutor</span><span class="p">.</span><span class="na">execute</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">result</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">job</span><span class="p">.</span><span class="na">execute</span><span class="p">()</span> |
| <span class="w"> </span><span class="n">analysisCallback</span><span class="p">(</span><span class="n">result</span><span class="p">)</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="n">job</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="p">}</span> |
| </code></pre></div> |
| <p>The Bugsnag uploader:</p> |
| <div class="highlight"><pre><span></span><code><span class="kd">class</span><span class="w"> </span><span class="nc">BugsnagHeapAnalysisUploader</span><span class="p">(</span><span class="n">applicationContext</span><span class="p">:</span><span class="w"> </span><span class="n">Application</span><span class="p">)</span><span class="w"> </span><span class="p">{</span> |
| |
| <span class="w"> </span><span class="kd">private</span><span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">bugsnagClient</span><span class="p">:</span><span class="w"> </span><span class="n">Client</span> |
| |
| <span class="w"> </span><span class="k">init</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="n">bugsnagClient</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">Client</span><span class="p">(</span> |
| <span class="w"> </span><span class="n">applicationContext</span><span class="p">,</span> |
| <span class="w"> </span><span class="n">BUGSNAG_API_KEY</span><span class="p">,</span> |
| <span class="w"> </span><span class="n">DO_NOT_ENABLE_EXCEPTION_HANDLER</span> |
| <span class="w"> </span><span class="p">)</span> |
| <span class="w"> </span><span class="n">bugsnagClient</span><span class="p">.</span><span class="na">setSendThreads</span><span class="p">(</span><span class="kc">false</span><span class="p">)</span> |
| <span class="w"> </span><span class="p">}</span> |
| |
| <span class="w"> </span><span class="kd">fun</span><span class="w"> </span><span class="nf">upload</span><span class="p">(</span><span class="n">heapAnalysis</span><span class="p">:</span><span class="w"> </span><span class="n">HeapAnalysis</span><span class="p">)</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="k">when</span><span class="w"> </span><span class="p">(</span><span class="n">heapAnalysis</span><span class="p">)</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="n">HeapAnalysisSuccess</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">exception</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">HeapAnalysisReport</span><span class="p">()</span> |
| <span class="w"> </span><span class="n">bugsnagClient</span><span class="p">.</span><span class="na">notify</span><span class="p">(</span><span class="n">exception</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">report</span><span class="w"> </span><span class="o">-></span> |
| <span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">metaData</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">report</span><span class="p">.</span><span class="na">error</span><span class="p">.</span><span class="na">metaData</span> |
| <span class="w"> </span><span class="n">metaData</span><span class="p">.</span><span class="na">addToTab</span><span class="p">(</span><span class="s">"Heap Analysis"</span><span class="p">,</span><span class="w"> </span><span class="s">"result"</span><span class="p">,</span><span class="w"> </span><span class="n">heapAnalysis</span><span class="p">.</span><span class="na">toString</span><span class="p">())</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="w"> </span><span class="k">is</span><span class="w"> </span><span class="n">HeapAnalysisFailure</span><span class="w"> </span><span class="o">-></span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="c1">// Please file any reported failure to</span> |
| <span class="w"> </span><span class="c1">// https://github.com/square/leakcanary/issues</span> |
| <span class="w"> </span><span class="n">bugsnagClient</span><span class="p">.</span><span class="na">notify</span><span class="p">(</span><span class="n">heapAnalysis</span><span class="p">.</span><span class="na">exception</span><span class="p">)</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="w"> </span><span class="p">}</span> |
| |
| <span class="w"> </span><span class="c1">// Exception with fake unique stacktrace to send all reports to the same error entry.</span> |
| <span class="w"> </span><span class="kd">class</span><span class="w"> </span><span class="nc">HeapAnalysisReport</span><span class="w"> </span><span class="p">:</span><span class="w"> </span><span class="n">Exception</span><span class="p">(</span><span class="s">"Check the HEAP ANALYSIS tab"</span><span class="p">)</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="kd">override</span><span class="w"> </span><span class="kd">fun</span><span class="w"> </span><span class="nf">fillInStackTrace</span><span class="p">():</span><span class="w"> </span><span class="n">Throwable</span><span class="w"> </span><span class="p">{</span> |
| <span class="w"> </span><span class="n">stackTrace</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">arrayOf</span><span class="p">(</span> |
| <span class="w"> </span><span class="n">StackTraceElement</span><span class="p">(</span> |
| <span class="w"> </span><span class="s">"HeapAnalysisReport"</span><span class="p">,</span> |
| <span class="w"> </span><span class="s">"analyzeHeap"</span><span class="p">,</span> |
| <span class="w"> </span><span class="s">"HeapAnalysisReport.kt"</span><span class="p">,</span> |
| <span class="w"> </span><span class="m">1</span> |
| <span class="w"> </span><span class="p">)</span> |
| <span class="w"> </span><span class="p">)</span> |
| <span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="k">this</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="w"> </span><span class="p">}</span> |
| |
| <span class="w"> </span><span class="kd">companion</span><span class="w"> </span><span class="kd">object</span><span class="w"> </span><span class="err">{</span> |
| <span class="w"> </span><span class="kd">private</span><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">BUGSNAG_API_KEY</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">YOUR_BUGSNAG_API_KEY</span> |
| <span class="w"> </span><span class="kd">private</span><span class="w"> </span><span class="kd">const</span><span class="w"> </span><span class="kd">val</span><span class="w"> </span><span class="nv">DO_NOT_ENABLE_EXCEPTION_HANDLER</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="kc">false</span> |
| <span class="w"> </span><span class="p">}</span> |
| <span class="p">}</span> |
| </code></pre></div> |
| <h3 id="more-leak-fixes-in-plumber">More leak fixes in Plumber<a class="headerlink" href="#more-leak-fixes-in-plumber" title="Permanent link">¶</a></h3> |
| <p>We added 3 new automatic fixes for known AOSP leaks in <code>plumber-android</code> (details: <a href="https://github.com/square/leakcanary/issues/1993">#1993</a>). As a reminder, <code>plumber-android</code> is automatically included when you add <code>leakcanary-android</code>, and you can add it manually for build types that don’t include LeakCanary:</p> |
| <div class="highlight"><pre><span></span><code>dependencies { |
| // leakcanary-android adds plumber-android to debug builds |
| debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.6' |
| |
| // This adds plumber-android to all build types |
| implementation 'com.squareup.leakcanary:plumber-android:2.6' |
| } |
| </code></pre></div> |
| <h3 id="bug-fixes-and-improvements_1">Bug fixes and improvements 🐛🔨<a class="headerlink" href="#bug-fixes-and-improvements_1" title="Permanent link">¶</a></h3> |
| <ul> |
| <li><a href="https://github.com/square/leakcanary/pull/1948">#1948</a> Leakcanary is now compiled against Kotlin 1.4 (while staying 1.3 compatible) to support <a href="https://kotlinlang.org/docs/reference/fun-interfaces.html">Functional (SAM) interfaces</a>.</li> |
| <li><a href="https://github.com/square/leakcanary/issues/1956">#1956</a> The retained object size is displayed as a human readable output (KB, MB, …).</li> |
| <li><a href="https://github.com/square/leakcanary/issues/1976">#1976</a> Improved default object inspectors and leak finders for <code>View</code> and <code>Context</code>.</li> |
| <li><a href="https://github.com/square/leakcanary/issues/1972">#1972</a> Fields are printed with the parent class name that holds the field in leak traces.</li> |
| <li><a href="https://github.com/square/leakcanary/issues/1981">#1981</a> Fixed StrictMode policy violation (main thread read from disk).</li> |
| <li><a href="https://github.com/square/leakcanary/issues/1977">#1977</a> Report objects that are not strongly reachable.</li> |
| <li><a href="https://github.com/square/leakcanary/pull/2018">#2018</a> & <a href="https://github.com/square/leakcanary/pull/2019">#2019</a> Fixed crashes in LeakCanary UI (discovered by Monkey tests).</li> |
| <li><a href="https://github.com/square/leakcanary/issues/2015">#2015</a> Fixed crash on Android < 16.</li> |
| <li><a href="https://github.com/square/leakcanary/issues/2023">#2023</a> Fixed crash in plugin projects.</li> |
| </ul> |
| <p>For more details, see the <a href="https://github.com/square/leakcanary/milestone/20">2.6 Milestone</a> and the <a href="https://github.com/square/leakcanary/compare/v2.5...v2.6">full diff</a>.</p> |
| <h2 id="version-25-2020-10-01">Version 2.5 (2020-10-01)<a class="headerlink" href="#version-25-2020-10-01" title="Permanent link">¶</a></h2> |
| <p>Please thank |
| <a href="https://github.com/Amokrane">@Amokrane</a>, |
| <a href="https://github.com/Armaxis">@Armaxis</a>, |
| <a href="https://github.com/askont">@askont</a>, |
| <a href="https://github.com/chao2zhang">@chao2zhang</a>, |
| <a href="https://github.com/daniil-shevtsov">@daniil-shevtsov</a>, |
| <a href="https://github.com/eygraber">@eygraber</a>, |
| <a href="https://github.com/msfjarvis">@msfjarvis</a>, |
| <a href="https://github.com/mzgreen">@mzgreen</a>, |
| <a href="https://github.com/lchen8">@lchen8</a>, |
| <a href="https://github.com/rpattabi">@rpattabi</a>, |
| <a href="https://github.com/sahil2441">@sahil2441</a>, |
| <a href="https://github.com/SylvainGirod">@SylvainGirod</a>, |
| <a href="https://github.com/vhow">@vhow</a> |
| for their contributions, bug reports and feature requests 🙏 🙏 🙏.</p> |
| <h3 id="heap-analysis-is-twice-as-fast">Heap analysis is twice as fast 🐤💨<a class="headerlink" href="#heap-analysis-is-twice-as-fast" title="Permanent link">¶</a></h3> |
| <p>No one asked, so we delivered! We rewrote several core components in Shark (LeakCanary’s heap analyzer) to dramatically reduce IO reads and allocations while keeping memory constant. More details on Twitter: <a href="https://twitter.com/ArtemChubaryan/status/1311078061895553030">thread by @ArtemChubaryan</a> and <a href="https://twitter.com/Piwai/status/1311085280753926144">thread by @Piwai</a>.</p> |
| <h3 id="compute-retained-size-within-the-leak-trace">Compute retained size within the leak trace<a class="headerlink" href="#compute-retained-size-within-the-leak-trace" title="Permanent link">¶</a></h3> |
| <p>Previously, LeakCanary computed the retained size for the leaking object (the last object in the leak trace). However, the bad reference causing objects to leak is often higher up in the leak trace and everything that it holds onto is actually leaking. So LeakCanary now computes the retained size for <a href="https://github.com/square/leakcanary/issues/1880">all the objects in the leaktrace that have a LEAKING or UNKNOWN status</a>:</p> |
| <div class="highlight"><pre><span></span><code>┬─── |
| │ GC Root: System class |
| │ |
| ├─ com.example.MySingleton class |
| │ Leaking: NO (a class is never leaking) |
| │ ↓ static MySingleton.leakedView |
| │ ~~~~~~~~~~ |
| ├─ android.widget.TextView instance |
| │ Leaking: YES (View.mContext references a destroyed activity) |
| │ Retaining 46326 bytes in 942 objects |
| │ ↓ TextView.mContext |
| ╰→ com.example.MainActivity instance |
| Leaking: YES (Activity#mDestroyed is true) |
| Retaining 1432 bytes in 36 objects |
| </code></pre></div> |
| <h3 id="disable-leakcanary-from-the-ui">Disable LeakCanary from the UI<a class="headerlink" href="#disable-leakcanary-from-the-ui" title="Permanent link">¶</a></h3> |
| <p>New toggle to disable <a href="https://github.com/square/leakcanary/issues/1886">heap dumping</a>, which can be useful for QA, or when doing a product demo. LeakCanary will still show a notification when an object is retained.</p> |
| <p><img alt="disable heap dumping" src="../images/disable_dumping.png" /></p> |
| <h3 id="deobfuscating-hprof-files">Deobfuscating hprof files<a class="headerlink" href="#deobfuscating-hprof-files" title="Permanent link">¶</a></h3> |
| <p>The <a href="../shark/#shark-cli">Shark CLI</a> can now <a href="https://github.com/square/leakcanary/issues/1698">deobfuscate heap dumps</a>:</p> |
| <div class="highlight"><pre><span></span><code>brew install leakcanary-shark |
| |
| shark-cli --hprof heapdump.hprof -m mapping.txt deobfuscate-hprof |
| </code></pre></div> |
| <h3 id="bug-fixes-and-improvements_2">Bug fixes and improvements 🐛🔨<a class="headerlink" href="#bug-fixes-and-improvements_2" title="Permanent link">¶</a></h3> |
| <ul> |
| <li>Heap analysis text results now <a href="https://github.com/square/leakcanary/issues/1811">wrap to a max width</a> when sharing them from the LeakCanary activity or printing to logcat. This will make it harder to miss details that are lost at the end of long lines of text.</li> |
| <li>The <code>leak_canary_watcher_auto_install</code>, <code>leak_canary_allow_in_non_debuggable_build</code> and <code>leak_canary_plumber_auto_install</code> resource booleans were <a href="https://github.com/square/leakcanary/issues/1863">meant to be public</a>.</li> |
| <li>We sprinkled a few <code>@JvmStatic</code> to <a href="https://github.com/square/leakcanary/issues/1870">help Java consummers</a>.</li> |
| <li>Fixed <a href="https://github.com/square/leakcanary/pull/1893">crash when no browser installed</a>.</li> |
| <li>Use distinct <a href="https://github.com/square/leakcanary/issues/1845">group for LeakCanary notifications</a>.</li> |
| <li>The heap analysis result now includes the <a href="https://github.com/square/leakcanary/pull/1931">heap dump duration</a> because it looks like Android 11 heap dumps are <a href="https://issuetracker.google.com/issues/168634429">sometimes super slow</a>. We also added more <a href="https://github.com/square/leakcanary/issues/1929">perf related metrics</a>.</li> |
| <li><a href="https://github.com/square/leakcanary/issues/1910">Disable logging</a> when AppWatcher runs in release builds.</li> |
| <li>Highlight library leak patterns <a href="https://github.com/square/leakcanary/issues/1916">directly within the leak traces</a>.</li> |
| <li>Improved inspections for <a href="https://github.com/square/leakcanary/issues/1912">Context, View</a> and <a href="https://github.com/square/leakcanary/pull/1884">ContextImpl</a>.</li> |
| </ul> |
| <p>For more details, see the <a href="https://github.com/square/leakcanary/milestone/19">2.5 Milestone</a> and the <a href="https://github.com/square/leakcanary/compare/v2.4...v2.5">full diff</a>.</p> |
| <h2 id="version-24-2020-06-10">Version 2.4 (2020-06-10)<a class="headerlink" href="#version-24-2020-06-10" title="Permanent link">¶</a></h2> |
| <p>Please thank |
| <a href="https://github.com/0x109">@0x109</a>, |
| <a href="https://github.com/andersu">@andersu</a>, |
| <a href="https://github.com/antoniomerlin">@antoniomerlin</a>, |
| <a href="https://github.com/bishiboosh">@bishiboosh</a>, |
| <a href="https://github.com/ckesc">@ckesc</a>, |
| <a href="https://github.com/jrodbx">@jrodbx</a>, |
| <a href="https://github.com/LouisCAD">@LouisCAD</a>, |
| <a href="https://github.com/marcardar">@marcardar</a>, |
| <a href="https://github.com/OlivierGenez">@OlivierGenez</a>, |
| <a href="https://github.com/pyricau">@pyricau</a>, |
| <a href="https://github.com/runningcode">@runningcode</a>, |
| <a href="https://github.com/seljad">@seljad</a>, |
| <a href="https://github.com/worldsnas">@worldsnas</a> |
| for their contributions, bug reports and feature requests.</p> |
| <h3 id="plumber-android-is-a-new-artifact-that-fixes-known-android-leaks"><code>plumber-android</code> is a new artifact that fixes known Android leaks 🚽🔧<a class="headerlink" href="#plumber-android-is-a-new-artifact-that-fixes-known-android-leaks" title="Permanent link">¶</a></h3> |
| <p>LeakCanary reports all leaks, including leaks caused by a known bug in 3<sup>rd</sup> party code that you do not have control over (reported as <a href="../fundamentals-how-leakcanary-works/#4-categorizing-leaks">Library leaks</a>). That can be annoying! LeakCanary now ships with a new dependency, <code>plumber-android</code>, which performs hacks at runtime to fix some of these known leaks. This releases has fixes for <strong>11 known leaks</strong>, but this is just the beginning. Contributions welcome! 🙏</p> |
| <p>Note that since the <code>leakcanary-android</code> dependency is usually added as a <code>debugImplementation</code> dependency, the <code>plumber-android</code> is transitively added only in debug builds, so it will not fix leaks in your release builds. You can add the dependency directly as <code>implementation</code> to get these fixes in release builds as well:</p> |
| <div class="highlight"><pre><span></span><code><span class="n">dependencies</span><span class="w"> </span><span class="o">{</span> |
| <span class="w"> </span><span class="n">implementation</span><span class="w"> </span><span class="s1">'com.squareup.leakcanary:plumber-android:2.4'</span> |
| <span class="o">}</span> |
| </code></pre></div> |
| <div class="admonition warning"> |
| <p class="admonition-title">Warning</p> |
| <p>While several of these fixes already ship in release builds of Square apps, this is the first official release of <code>plumber-android</code>, so you should consider it <strong>experimental</strong>.</p> |
| </div> |
| <h3 id="analyzing-leaks-from-the-cli-is-easier-than-ever">Analyzing leaks from the CLI is easier than ever 🍺<a class="headerlink" href="#analyzing-leaks-from-the-cli-is-easier-than-ever" title="Permanent link">¶</a></h3> |
| <p>The <a href="../shark/#shark-cli">Shark CLI</a> can now be installed via <a href="https://brew.sh/">Homebrew</a></p> |
| <div class="highlight"><pre><span></span><code>brew install leakcanary-shark |
| </code></pre></div> |
| <p>You can then look for leaks in apps on any connected device, for example:</p> |
| <div class="highlight"><pre><span></span><code>$ shark-cli --device emulator-5554 --process com.example.app.debug analyze |
| </code></pre></div> |
| <h3 id="support-for-android-test-orchestrator">Support for Android Test Orchestrator 🎼<a class="headerlink" href="#support-for-android-test-orchestrator" title="Permanent link">¶</a></h3> |
| <p>If you set up LeakCanary to report test failures when detecting leaks in instrumentation tests, it <a href="https://github.com/square/leakcanary/issues/1046">now works</a> with Android Test Orchestrator as well. No change required, LeakCanary will automatically detect thatAndroid Test Orchestrator is running and hook into it.</p> |
| <h3 id="no-more-master-branch">No more <code>master</code> branch<a class="headerlink" href="#no-more-master-branch" title="Permanent link">¶</a></h3> |
| <p>The branch name <code>master</code> comes from the <em>master / slave</em> terminology. We renamed the default branch to <code>main</code>, a small step towards making the LeakCanary community a safer space. Here’s a good <a href="https://twitter.com/mislav/status/1270388510684598272">thread on this topic</a>.</p> |
| <h3 id="bug-fixes-and-improvements_3">Bug fixes and improvements 🐛🔨<a class="headerlink" href="#bug-fixes-and-improvements_3" title="Permanent link">¶</a></h3> |
| <ul> |
| <li>URLs in <em>Library Leak</em> descriptions are <a href="https://github.com/square/leakcanary/issues/1844">now clickable</a></li> |
| <li>Fixed <a href="https://github.com/square/leakcanary/issues/1832">ordering issues</a> causing improper config with manual setup. A related change is that <code>AppWatcher.Config.enabled</code> is now deprecated.</li> |
| <li>Fixed possible <a href="https://github.com/square/leakcanary/issues/1798">OutOfMemoryError failure</a> when computing retained size: we were loading to memory large arrays from the heap dump just to get their size.</li> |
| </ul> |
| <p>For more details, see the <a href="https://github.com/square/leakcanary/milestone/18">2.4 Milestone</a> and the <a href="https://github.com/square/leakcanary/compare/v2.3...v2.4">full diff</a>.</p> |
| <h2 id="version-23-2020-04-08">Version 2.3 (2020-04-08)<a class="headerlink" href="#version-23-2020-04-08" title="Permanent link">¶</a></h2> |
| <p>This is a minor release on the feature front, but a large release on the documentation front!</p> |
| <p>Many thanks to |
| <a href="https://github.com/adamfit">@adamfit</a>, |
| <a href="https://github.com/Amokrane">@Amokrane</a>, |
| <a href="https://github.com/Armaxis">@Armaxis</a>, |
| <a href="https://github.com/artnc">@artnc</a>, |
| <a href="https://github.com/burakeregar">@burakeregar</a>, |
| <a href="https://github.com/ClaasJG">@ClaasJG</a>, |
| <a href="https://github.com/clementcontet">@clementcontet</a>, |
| <a href="https://github.com/ckesc">@ckesc</a>, |
| <a href="https://github.com/cketti">@cketti</a>, |
| <a href="https://github.com/fbenbassat">@fbenbassat</a>, |
| <a href="https://github.com/Guneetgstar">@Guneetgstar</a>, |
| <a href="https://github.com/Igorxp5">@Igorxp5</a>, |
| <a href="https://github.com/JLLeitschuh">@JLLeitschuh</a>, |
| <a href="https://github.com/KidAndroid">@KidAndroid</a>, |
| <a href="https://github.com/ligi">@ligi</a>, |
| <a href="https://github.com/mzgreen">@mzgreen</a>, |
| <a href="https://github.com/pyricau">@pyricau</a>, |
| <a href="https://github.com/sprintuu">@sprintuu</a>, |
| <a href="https://github.com/tevjef">@tevjef</a>, |
| <a href="https://github.com/thrlr123">@thrlr123</a> |
| for the contributions, bug reports and feature requests.</p> |
| <p>We <a href="https://twitter.com/Piwai/status/1253454280758980609">asked for help</a> and immediately started seeing more contributions. Thanks all! Check out the <a href="../how_to_help/">How to help</a> page.</p> |
| <h3 id="leakcanary-will-now-crash-in-release-builds">LeakCanary will now crash in release builds<a class="headerlink" href="#leakcanary-will-now-crash-in-release-builds" title="Permanent link">¶</a></h3> |
| <p>Despite the documentation insisting on using <code>debugImplementation</code>, we’ve seen apps <a href="https://twitter.com/Piwai/status/1245524534712602624">ship LeakCanary</a> in <strong>release builds</strong>. Mistakes happen, so we’ve made that mistake <a href="https://github.com/square/leakcanary/issues/1804">harder to miss</a> by making LeakCanary <strong>crash when included in release builds</strong>.</p> |
| <p>Learn More: <a href="../recipes/#leakcanary-in-release-builds">LeakCanary in release builds</a>.</p> |
| <h3 id="doc-site">Doc site 🛀💥<a class="headerlink" href="#doc-site" title="Permanent link">¶</a></h3> |
| <p>The doc site content has changed quite a bit! We applied advice from <a href="https://developers.google.com/tech-writing/">Google’s tech writing guide</a>. If you’ve been confused by <em>Library Leaks</em> before, check out see the new <a href="../fundamentals-how-leakcanary-works/#4-categorizing-leaks">Categorizing leaks</a> section. Take a look around, let us know what you think.</p> |
| <h3 id="bug-fixes-and-improvements_4">Bug fixes and improvements 😉<a class="headerlink" href="#bug-fixes-and-improvements_4" title="Permanent link">¶</a></h3> |
| <ul> |
| <li>The new <a href="../recipes/#using-leakcanary-with-obfuscated-apps">deobfuscation Gradle plugin</a> wasn’t working <a href="https://github.com/square/leakcanary/issues/1761">with Gradle 3.6</a>, this is now fixed. Also removed the requirement for the plugin to be <a href="https://github.com/square/leakcanary/pull/1816">applied after AGP</a>.</li> |
| <li>Fixed 2 crashes (<a href="https://github.com/square/leakcanary/issues/1768">#1768</a> & <a href="https://github.com/square/leakcanary/issues/1769">#1769</a>) in the LeakCanary UI found by a sneaky monkey runner 🙈.</li> |
| <li>The LeakCanary UI updates <a href="https://github.com/square/leakcanary/issues/1742">immediately</a> when a heap analysis is added or deleted.</li> |
| <li>Fixed a crash when <a href="https://github.com/square/leakcanary/pull/1800">updating from LeakCanary 2.0</a>.</li> |
| <li>The <em>About</em> section of the LeakCanary now surfaces whether heap dumping is <a href="https://github.com/square/leakcanary/issues/1803">currently enabled</a>.</li> |
| <li>Fixed process <a href="https://github.com/square/leakcanary/issues/1711">not exiting</a> in SharkCLI on Windows.</li> |
| <li>Improved <a href="https://github.com/square/leakcanary/pull/1823">error message</a> when obfuscation mappings appear to be missing.</li> |
| </ul> |
| <p>For more details, see the <a href="https://github.com/square/leakcanary/milestone/17">2.3 Milestone</a> and the <a href="https://github.com/square/leakcanary/compare/v2.2...v2.3">full diff</a>.</p> |
| <h2 id="version-22-2020-02-05">Version 2.2 (2020-02-05)<a class="headerlink" href="#version-22-2020-02-05" title="Permanent link">¶</a></h2> |
| <p>We’ve got some good stuff for the first release of the decade!</p> |
| <p>Many thanks to |
| <a href="https://github.com/AndroidInternal">@AndroidInternal</a>, |
| <a href="https://github.com/Armaxis">@Armaxis</a>, |
| <a href="https://github.com/lic2050">@lic2050</a>, |
| <a href="https://github.com/mzgreen">@mzgreen</a>, |
| <a href="https://github.com/orenktaboola">@orenktaboola</a>, |
| <a href="https://github.com/personshelldon">@personshelldon</a>, |
| <a href="https://github.com/Plastix">@Plastix</a>, |
| <a href="https://github.com/pyricau">@pyricau</a> |
| for the contributions, bug reports and feature requests.</p> |
| <h3 id="viewmodel-leak-detection">ViewModel leak detection<a class="headerlink" href="#viewmodel-leak-detection" title="Permanent link">¶</a></h3> |
| <p><a href="https://developer.android.com/topic/libraries/architecture/viewmodel">Android ViewModels</a> are really cool! Their lifecycle is much nicer than fragments or activities, but sometimes mistakes happen. LeakCanary will now automatically detect ViewModel leaks and report any ViewModel instance retained after its <code>onCleared()</code> method was called.</p> |
| <h3 id="android-tv">Android TV<a class="headerlink" href="#android-tv" title="Permanent link">¶</a></h3> |
| <p><img alt="tv ui" src="../images/android-tv-leaks.png" /></p> |
| <p>LeakCanary is finally coming to big screens near you! Best part - no additional setup is required, just enable it like you would for a <a href="../getting_started/">mobile device</a>. Now whenever there’s a leak - you will see a helpful Toast appear with all the details. Make sure to check out our new <a href="../recipes/#android-tv">Android TV</a> section and chill!</p> |
| <h3 id="java-friendly-config-builders">Java-friendly Config builders<a class="headerlink" href="#java-friendly-config-builders" title="Permanent link">¶</a></h3> |
| <p><a href="https://github.com/square/leakcanary/issues/1714">It was brought to our attention</a> that configuring <code>LeakCanary</code> and <code>AppWatcher</code> was a miserable experience from Java code. Well, not anymore!</p> |
| <p>Now you can use <code>LeakCanary.Config.Builder</code> and <code>AppWatcher.Config.Builder</code> to have idiomatic Java when updating the configurations. For example:</p> |
| <div class="highlight"><pre><span></span><code>LeakCanary.Config config = LeakCanary.getConfig().newBuilder() |
| .retainedVisibleThreshold(3) |
| .computeRetainedHeapSize(false) |
| .build(); |
| LeakCanary.setConfig(config); |
| </code></pre></div> |
| <p>If you notice any other problems when using LeakCanary from Java, please <a href="https://github.com/square/leakcanary/issues/new?assignees=&labels=type%3A+enhancement&template=3-feature.md&title=">file an issue</a>! We take Java-interop seriously and will be happy to improve LeakCanary’s API!</p> |
| <p>For more details, see the <a href="https://github.com/square/leakcanary/milestone/16">2.2 Milestone</a> and the <a href="https://github.com/square/leakcanary/compare/v2.1...v2.2">full diff</a>.</p> |
| <h2 id="version-21-2019-12-31">Version 2.1 (2019-12-31)<a class="headerlink" href="#version-21-2019-12-31" title="Permanent link">¶</a></h2> |
| <p>A special New Year’s Eve release 🥳, the next release will be in another decade 😎!</p> |
| <p>Many thanks to |
| <a href="https://github.com/adamfit">@adamfit</a>, |
| <a href="https://github.com/alexander-smityuk">@alexander-smityuk</a>, |
| <a href="https://github.com/Armaxis">@Armaxis</a>, |
| <a href="https://github.com/BraisGabin">@BraisGabin</a>, |
| <a href="https://github.com/devism">@devism</a>, |
| <a href="https://github.com/ditclear">@ditclear</a>, |
| <a href="https://github.com/jrodbx">@jrodbx</a>, |
| <a href="https://github.com/jstefanowski">@jstefanowski</a>, |
| <a href="https://github.com/Maragues">@Maragues</a>, |
| <a href="https://github.com/mzgreen">@mzgreen</a>, |
| <a href="https://github.com/pyricau">@pyricau</a> |
| for the contributions, bug reports and feature requests.</p> |
| <h3 id="a-gradle-plugin-for-obfuscated-apps">A Gradle plugin for obfuscated apps<a class="headerlink" href="#a-gradle-plugin-for-obfuscated-apps" title="Permanent link">¶</a></h3> |
| <p>It’s fairly common for teams to have a QA build that is tested before making the release build. Usually that build will be obfuscated (via Proguard or R8), but also add LeakCanary to detect leaks during QA. This leads to obfuscated leak traces, which are hard to understand 🤯. Check out our new <a href="../recipes/#using-leakcanary-with-obfuscated-apps">Gradle deobfuscation plugin</a> and rejoice!</p> |
| <h3 id="ui-twix-tweaks">UI <strike>twix</strike> tweaks<a class="headerlink" href="#ui-twix-tweaks" title="Permanent link">¶</a></h3> |
| <p>In 2.0 we changed the LeakCanary UI and UX, and built a foundation on which 2.1 extends.</p> |
| <p><img alt="ui" src="../images/screenshot-2.0.png" /></p> |
| <ul> |
| <li>Since 2.0, Leaks are grouped by their distinct signature. In 2.1 there’s a <code>New</code> tag that will show until you open up a leak. There’s also a <code>Library Leak</code> tag for leaks that are known to be caused by a bug in the Android Framework or Google libraries, and the library leak description now shows up in the UI.</li> |
| <li>The type of the Java objects (class, instance, array) is now displayed in the LeakTrace, e.g. see <code>FontsContract class</code> and <code>ExampleApplication instance</code> above.</li> |
| <li>The type of the GC root now shows up at the root of the leak trace. Makes sense!</li> |
| <li>The leak result notification has an importance now set to MAX so that it’ll show up right in your face. If you turn it off, the canary will haunt you in your dreams 🐤👻. To save your sanity and your device battery, automatic heap dumps now won’t happen more often than once per minute.</li> |
| <li>The resource id name for <code>View</code> instances is now displayed in the leak trace. You shouldn’t look at the <a href="https://github.com/square/leakcanary/pull/1663">implementation</a>.</li> |
| </ul> |
| <div class="highlight"><pre><span></span><code>├─ android.widget.TextView instance |
| │ View.mID = R.id.helper_text |
| </code></pre></div> |
| <h3 id="documentation-goodies">Documentation goodies<a class="headerlink" href="#documentation-goodies" title="Permanent link">¶</a></h3> |
| <ul> |
| <li>The <a href="../fundamentals/">Fundamentals</a> page was entirely rewritten, split into 3 pages and moved to its own tab. Please read it and provide feedback!</li> |
| <li>At Square, we have been uploading leaks to Bugsnag for 3 years now, so that no leak ever gets missed. Follow <a href="../uploading/">this recipe</a>!</li> |
| <li>Did you know you can <a href="../recipes/#detecting-leaks-in-jvm-applications">run LeakCanary in a JVM</a>?</li> |
| </ul> |
| <h3 id="api-breaking-bettering-changes">API <strike>breaking</strike> bettering changes<a class="headerlink" href="#api-breaking-bettering-changes" title="Permanent link">¶</a></h3> |
| <ul> |
| <li>The APIs of the <code>Leak</code> and <code>LeakTrace</code> classes have significantly changed, e.g. all <code>LeakTrace</code> instances with an identical signature are grouped under the same Leak object. Despite these breaking changes, this release version is a minor update. Oh noes, what about semantic versioning 😱? Ask Don Quixote.</li> |
| <li>You can now customize the way LeakCanary finds the leaking objects in the heap dump. For example, here’s the configuration SharkCli uses to find leaks in heap dumps of apps that don’t even have the LeakCanary dependency:</li> |
| </ul> |
| <div class="highlight"><pre><span></span><code><span class="n">LeakCanary</span><span class="p">.</span><span class="na">config</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">LeakCanary</span><span class="p">.</span><span class="na">config</span><span class="p">.</span><span class="na">copy</span><span class="p">(</span> |
| <span class="w"> </span><span class="n">leakingObjectFinder</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">FilteringLeakingObjectFinder</span><span class="p">(</span> |
| <span class="w"> </span><span class="n">AndroidObjectInspectors</span><span class="p">.</span><span class="na">appLeakingObjectFilters</span> |
| <span class="w"> </span><span class="p">)</span> |
| <span class="p">)</span> |
| </code></pre></div> |
| <ul> |
| <li>LeakCanary automatically disables itself in tests by detecting that the <code>org.junit.Test</code> is in the classpath. Unfortunately, some apps ship Junit in their app debug classpath (e.g. when using OkHttp MockWebServer). You can now customize which class is used to detect tests:</li> |
| </ul> |
| <div class="highlight"><pre><span></span><code><span class="nt"><resources></span> |
| <span class="w"> </span><span class="nt"><string</span><span class="w"> </span><span class="na">name=</span><span class="s">"leak_canary_test_class_name"</span><span class="nt">></span>assertk.Assert<span class="nt"></string></span> |
| <span class="nt"></resources></span> |
| </code></pre></div> |
| <h3 id="interactive-cli">Interactive CLI<a class="headerlink" href="#interactive-cli" title="Permanent link">¶</a></h3> |
| <p><a href="https://github.com/square/leakcanary/releases/download/v2.1/shark-cli-2.1.zip">Shark CLI</a> was rewritten on top of <a href="https://github.com/ajalt/clikt">Clikt</a>:</p> |
| <div class="highlight"><pre><span></span><code>$<span class="w"> </span>shark-cli |
| Usage:<span class="w"> </span>shark-cli<span class="w"> </span><span class="o">[</span>OPTIONS<span class="o">]</span><span class="w"> </span>COMMAND<span class="w"> </span><span class="o">[</span>ARGS<span class="o">]</span>... |
| |
| <span class="w"> </span>^<span class="sb">`</span>.<span class="w"> </span>.<span class="o">=</span><span class="s2">""</span><span class="o">=</span>. |
| <span class="w"> </span>^_<span class="w"> </span><span class="se">\ </span><span class="w"> </span><span class="se">\ </span><span class="w"> </span>/<span class="w"> </span>_<span class="w"> </span>_<span class="w"> </span><span class="se">\</span> |
| <span class="w"> </span><span class="se">\ \ </span><span class="w"> </span><span class="o">{</span><span class="w"> </span><span class="se">\ </span><span class="w"> </span><span class="p">|</span><span class="w"> </span>d<span class="w"> </span>b<span class="w"> </span><span class="p">|</span> |
| <span class="w"> </span><span class="o">{</span><span class="w"> </span><span class="se">\ </span><span class="w"> </span>/<span class="w"> </span><span class="sb">`</span>~~~--__<span class="w"> </span><span class="se">\ </span><span class="w"> </span>/<span class="se">\ </span><span class="w"> </span>/ |
| <span class="w"> </span><span class="o">{</span><span class="w"> </span><span class="se">\_</span>__----~~<span class="s1">' `~~-_/'</span>-<span class="o">=</span><span class="se">\/</span><span class="o">=</span>-<span class="s1">'\,</span> |
| <span class="s1"> \ /// a `~. \ \</span> |
| <span class="s1"> / /~~~~-, ,__. , /// __,,,,) \ |</span> |
| <span class="s1"> \/ \/ `~~~; ,---~~-_`/ \ / \/</span> |
| <span class="s1"> / / '</span>.<span class="w"> </span>.<span class="s1">'</span> |
| <span class="s1"> '</span>._.<span class="err">'</span><span class="w"> </span>_<span class="p">|</span><span class="sb">`</span>~~<span class="sb">`</span><span class="p">|</span>_ |
| <span class="w"> </span>/<span class="p">|</span><span class="se">\ </span><span class="w"> </span>/<span class="p">|</span><span class="se">\</span> |
| |
| Options: |
| <span class="w"> </span>-p,<span class="w"> </span>--process<span class="w"> </span>NAME<span class="w"> </span>Full<span class="w"> </span>or<span class="w"> </span>partial<span class="w"> </span>name<span class="w"> </span>of<span class="w"> </span>a<span class="w"> </span>process,<span class="w"> </span>e.g. |
| <span class="w"> </span><span class="s2">"example"</span><span class="w"> </span>would<span class="w"> </span>match<span class="w"> </span><span class="s2">"com.example.app"</span> |
| <span class="w"> </span>-d,<span class="w"> </span>--device<span class="w"> </span>ID<span class="w"> </span>device/emulator<span class="w"> </span>id |
| <span class="w"> </span>-m,<span class="w"> </span>--obfuscation-mapping<span class="w"> </span>PATH<span class="w"> </span>path<span class="w"> </span>to<span class="w"> </span>obfuscation<span class="w"> </span>mapping<span class="w"> </span>file |
| <span class="w"> </span>--verbose<span class="w"> </span>/<span class="w"> </span>--no-verbose<span class="w"> </span>provide<span class="w"> </span>additional<span class="w"> </span>details<span class="w"> </span>as<span class="w"> </span>to<span class="w"> </span>what |
| <span class="w"> </span>shark-cli<span class="w"> </span>is<span class="w"> </span>doing |
| <span class="w"> </span>-h,<span class="w"> </span>--hprof<span class="w"> </span>FILE<span class="w"> </span>path<span class="w"> </span>to<span class="w"> </span>a<span class="w"> </span>.hprof<span class="w"> </span>file |
| <span class="w"> </span>--help<span class="w"> </span>Show<span class="w"> </span>this<span class="w"> </span>message<span class="w"> </span>and<span class="w"> </span><span class="nb">exit</span> |
| |
| Commands: |
| <span class="w"> </span>interactive<span class="w"> </span>Explore<span class="w"> </span>a<span class="w"> </span>heap<span class="w"> </span>dump. |
| <span class="w"> </span>analyze<span class="w"> </span>Analyze<span class="w"> </span>a<span class="w"> </span>heap<span class="w"> </span>dump. |
| <span class="w"> </span>dump-process<span class="w"> </span>Dump<span class="w"> </span>the<span class="w"> </span>heap<span class="w"> </span>and<span class="w"> </span>pull<span class="w"> </span>the<span class="w"> </span>hprof<span class="w"> </span>file. |
| <span class="w"> </span>strip-hprof<span class="w"> </span>Replace<span class="w"> </span>all<span class="w"> </span>primitive<span class="w"> </span>arrays<span class="w"> </span>from<span class="w"> </span>the<span class="w"> </span>provided<span class="w"> </span>heap<span class="w"> </span>dump<span class="w"> </span>with |
| <span class="w"> </span>arrays<span class="w"> </span>of<span class="w"> </span>zeroes<span class="w"> </span>and<span class="w"> </span>generate<span class="w"> </span>a<span class="w"> </span>new<span class="w"> </span><span class="s2">"-stripped.hprof"</span><span class="w"> </span>file. |
| </code></pre></div> |
| <p>There’s a new <code>interactive</code> command which enables exploring the heap dump from the command line:</p> |
| <div class="highlight"><pre><span></span><code>$<span class="w"> </span>shark-cli<span class="w"> </span>-h<span class="w"> </span>heapdump.hprof<span class="w"> </span>interactive |
| Enter<span class="w"> </span><span class="nb">command</span><span class="w"> </span><span class="o">[</span>help<span class="o">]</span>: |
| <span class="nb">help</span> |
| |
| Available<span class="w"> </span>commands: |
| <span class="w"> </span>analyze<span class="w"> </span>Analyze<span class="w"> </span>the<span class="w"> </span>heap<span class="w"> </span>dump. |
| <span class="w"> </span>class<span class="w"> </span>NAME@ID<span class="w"> </span>Show<span class="w"> </span>class<span class="w"> </span>with<span class="w"> </span>a<span class="w"> </span>matching<span class="w"> </span>NAME<span class="w"> </span>and<span class="w"> </span>Object<span class="w"> </span>ID. |
| <span class="w"> </span>instance<span class="w"> </span>CLASS_NAME@ID<span class="w"> </span>Show<span class="w"> </span>instance<span class="w"> </span>with<span class="w"> </span>a<span class="w"> </span>matching<span class="w"> </span>CLASS_NAME<span class="w"> </span>and<span class="w"> </span>Object |
| ID. |
| <span class="w"> </span>array<span class="w"> </span>CLASS_NAME@ID<span class="w"> </span>Show<span class="w"> </span>array<span class="w"> </span>instance<span class="w"> </span>with<span class="w"> </span>a<span class="w"> </span>matching<span class="w"> </span>CLASS_NAME<span class="w"> </span>and |
| Object<span class="w"> </span>ID. |
| <span class="w"> </span>->instance<span class="w"> </span>CLASS_NAME@ID<span class="w"> </span>Show<span class="w"> </span>path<span class="w"> </span>from<span class="w"> </span>GC<span class="w"> </span>Roots<span class="w"> </span>to<span class="w"> </span>instance. |
| <span class="w"> </span>~>instance<span class="w"> </span>CLASS_NAME@ID<span class="w"> </span>Show<span class="w"> </span>path<span class="w"> </span>from<span class="w"> </span>GC<span class="w"> </span>Roots<span class="w"> </span>to<span class="w"> </span>instance,<span class="w"> </span>highlighting |
| suspect<span class="w"> </span>references. |
| <span class="w"> </span><span class="nb">help</span><span class="w"> </span>Show<span class="w"> </span>this<span class="w"> </span>message. |
| <span class="w"> </span><span class="nb">exit</span><span class="w"> </span>Exit<span class="w"> </span>this<span class="w"> </span>interactive<span class="w"> </span>prompt. |
| </code></pre></div> |
| <p>We’re currently exploring the idea of adding <a href="https://twitter.com/Piwai/status/1211795647273160704">support for SQL queries</a>, feedback welcome!</p> |
| <p>For more details, see the <a href="https://github.com/square/leakcanary/milestone/15">2.1 Milestone</a> and the <a href="https://github.com/square/leakcanary/compare/v2.0...v2.1">full diff</a>.</p> |
| <h2 id="version-20-2019-11-27">Version 2.0 (2019-11-27)<a class="headerlink" href="#version-20-2019-11-27" title="Permanent link">¶</a></h2> |
| <p>In the past 7 months, LeakCanary went through 3 alphas and 5 betas, encompassing 23 contributors over 493 commits, 35826 insertions and 10156 deletions.</p> |
| <h3 id="should-i-upgrade">Should I upgrade?<a class="headerlink" href="#should-i-upgrade" title="Permanent link">¶</a></h3> |
| <p><strong>YES!</strong> LeakCanary 2 is so much better, it might make you excited when you see a new memory leak. Follow the <a href="../upgrading-to-leakcanary-2.0/">upgrade guide</a>, you won’t regret it!</p> |
| <h3 id="so-whats-changed-since-163">So, what’s changed since 1.6.3?<a class="headerlink" href="#so-whats-changed-since-163" title="Permanent link">¶</a></h3> |
| <p><strong>Everything.</strong> The LeakCanary codebase went from <strong>~6000</strong> lines of Java to <strong>~16000</strong> lines of Kotlin, excluding comments & blanks.</p> |
| <div class="admonition question"> |
| <p class="admonition-title">Isn’t Kotlin supposed to drastically reduce the amount of boilerplate code?</p> |
| <p>Absolutely! And it did. But then, we wrote more code. |
| LeakCanary used to depend on <a href="https://github.com/square/haha">HAHA</a>, a repackaging of <a href="https://android.googlesource.com/platform/tools/base/+/2f03004c181baf9d291a9bf992e1b444e83cd82d/perflib/">perflib</a>, the heap dump parser used by Android Studio. Unfortunately perflib was slow and used too much memory, so LeakCanary now includes its own heap dump parser: <a href="../shark/">Shark</a>. The extra code comes from Shark, but also from having a lot more automated tests, and an improved UI layer.</p> |
| </div> |
| <p>One major difference: when the app is in foreground, LeakCanary 2 will not trigger on every retained instance. Instead it will wait until the app goes in background or to reach a threashold of 5 retained instances in foreground. The analysis will then find all the leaks at once, and group identical leaks in the results UI. Please read the <a href="../fundamentals/">Fundamentals</a> section to learn more!</p> |
| <h3 id="random-facts">Random facts<a class="headerlink" href="#random-facts" title="Permanent link">¶</a></h3> |
| <ul> |
| <li>You can customize the Leaks launcher icon and label: <a href="../recipes/#icon-and-label">learn more here</a>.</li> |
| <li>If you ` press on your main activity launcher icon, you should see a LeakCanary dynamic shortcut. You can then long press that to drop it on your home screen, and the launcher shows that it’s the leaks launcher for your app.</li> |
| <li>Out of the box, LeakCanary tracks all fragments flavors: AOSP, Support Library and Android X.</li> |
| <li>From within the leak screen, you can share a leak to stack overflow. You can also share a heap dump, or import and analyze a heap dump from another device.</li> |
| <li>You can run LeakCanary from your computer command line, on any debuggable app even if that app doesn’t have LeakCanary: <a href="../shark/##shark-cli">learn more here</a>.</li> |
| <li>The new documentation is fully searchable and includes the API documentation. Try the search bar ⤴.</li> |
| <li>A large 160Mb heap dump uses 2Gb memory when opening it in Android Studio, but only 40Mb with Shark.</li> |
| </ul> |
| <h3 id="changes-since-20-beta-5">Changes since 2.0 Beta 5<a class="headerlink" href="#changes-since-20-beta-5" title="Permanent link">¶</a></h3> |
| <ul> |
| <li>Shark CLI supports multiple connected devices <a href="https://github.com/square/leakcanary/issues/1642">#1642</a></li> |
| <li>Fixed missing sources from Maven Central <a href="https://github.com/square/leakcanary/issues/1643">#1643</a></li> |
| <li>Updated notification icon to avoid confusion with Twitter DM notifications, and added icons to bottom navigation bar <a href="https://github.com/square/leakcanary/pull/1648">#1648</a></li> |
| <li>Automatic leak detection for support library fragments <a href="https://github.com/square/leakcanary/pull/1611">#1611</a></li> |
| </ul> |
| <p>Many thanks to |
| <a href="https://github.com/AndreasBoehm">@AndreasBoehm</a>, |
| <a href="https://github.com/jrodbx">@jrodbx</a>, |
| <a href="https://github.com/pyricau">@pyricau</a> |
| for the contributions, bug reports and feature requests.</p> |
| <p>For more details, see the <a href="https://github.com/square/leakcanary/milestone/14">2.0 Milestone</a> and the <a href="https://github.com/square/leakcanary/compare/v2.0-beta-5...v2.0">full diff</a>.</p> |
| <h2 id="version-20-beta-5-2019-11-25">Version 2.0 Beta 5 (2019-11-25)<a class="headerlink" href="#version-20-beta-5-2019-11-25" title="Permanent link">¶</a></h2> |
| <ul> |
| <li>Major bugfix: native gc roots were accidentally ignored in Beta 4, as a result some leaks were not found <a href="https://github.com/square/leakcanary/issues/1634">#1634</a></li> |
| <li>Fixed Lint warning (<code>leak_canary_about_message</code> string triggered <em>multiple substitutions</em> warning) <a href="https://github.com/square/leakcanary/issues/1630">#1630</a></li> |
| </ul> |
| <p>Many thanks to |
| <a href="https://github.com/DanEdgarTarget">@DanEdgarTarget</a>, |
| <a href="https://github.com/msfjarvis">@msfjarvis</a>, |
| <a href="https://github.com/pyricau">@PaulWoitaschek</a>, |
| <a href="https://github.com/pyricau">@pyricau</a>, |
| <a href="https://github.com/ZacSweers">@ZacSweers</a> |
| for the contributions, bug reports and feature requests.</p> |
| <p>For more details, see the <a href="https://github.com/square/leakcanary/milestone/13">2.0-beta-5 Milestone</a> and the <a href="https://github.com/square/leakcanary/compare/v2.0-beta-4...v2.0-beta-5">full diff</a>.</p> |
| <h2 id="version-20-beta-4-2019-11-18">Version 2.0 Beta 4 (2019-11-18)<a class="headerlink" href="#version-20-beta-4-2019-11-18" title="Permanent link">¶</a></h2> |
| <ul> |
| <li>Improved string rendering for heap analysis results</li> |
| <li>UX redesign <a href="https://github.com/square/leakcanary/issues/1445">#1445</a></li> |
| <li>Support for pattern matching of native reference leaks <a href="https://github.com/square/leakcanary/issues/1562">#1562</a></li> |
| <li>Added support for deobfuscation using Proguard mapping files in Shark <a href="https://github.com/square/leakcanary/issues/1499">#1499</a>. This isn’t directly supported in LeakCanary yet.</li> |
| <li>Added support for extracting metadata from the heap dump (see the <a href="../recipes/#extracting-metadata-from-the-heap-dump">recipe</a>) <a href="https://github.com/square/leakcanary/issues/1519">#1519</a></li> |
| <li>Improved auto disabling of LeakCanary in Unit and UI tests <a href="https://github.com/square/leakcanary/issues/1552">#1552</a></li> |
| <li>Several performance improvements when parsing heap dumps</li> |
| <li>Fixed several bugs and crashes</li> |
| <li>Added new known leak patterns</li> |
| </ul> |
| <p>Many thanks to |
| <a href="https://github.com/Armaxis">@Armaxis</a>, |
| <a href="https://github.com/BraisGabin">@BraisGabin</a>, |
| <a href="https://github.com/bric3">@bric3</a>, |
| <a href="https://github.com/elihart">@elihart</a>, |
| <a href="https://github.com/fernandospr">@fernandospr</a>, |
| <a href="https://github.com/flickator">@flickator</a>, |
| <a href="https://github.com/gabrysgab">@gabrysgab</a>, |
| <a href="https://github.com/JorgeDLS">@JorgeDLS</a>, |
| <a href="https://github.com/lannyf77">@lannyf77</a>, |
| <a href="https://github.com/msfjarvis">@msfjarvis</a>, |
| <a href="https://github.com/mzgreen">@mzgreen</a>, |
| <a href="https://github.com/ozmium">@ozmium</a>, |
| <a href="https://github.com/pyricau">@PaulWoitaschek</a>, |
| <a href="https://github.com/pyricau">@pyricau</a>, |
| <a href="https://github.com/shelpy">@shelpy</a>, |
| <a href="https://github.com/vRallev">@vRallev</a>, |
| <a href="https://github.com/ZacSweers">@ZacSweers</a> |
| for the contributions, bug reports and feature requests.</p> |
| <p>For more details, see the <a href="https://github.com/square/leakcanary/milestone/12">2.0-beta-4 Milestone</a> and the <a href="https://github.com/square/leakcanary/compare/v2.0-beta-3...v2.0-beta-4">full diff</a>.</p> |
| <h2 id="version-20-beta-3-2019-08-22">Version 2.0 Beta 3 (2019-08-22)<a class="headerlink" href="#version-20-beta-3-2019-08-22" title="Permanent link">¶</a></h2> |
| <ul> |
| <li>Baseline memory usage for large hprofs divided by 3 and removed memory spikes <a href="https://github.com/square/leakcanary/pull/1543">#1543</a></li> |
| <li>Fixed crash when LeakCanary is initialized from another process <a href="https://github.com/square/leakcanary/issues/1529">#1529</a></li> |
| <li>Java local references are deprioritized to look for longer alternative paths <a href="https://github.com/square/leakcanary/pull/1525">#1525</a></li> |
| <li>Fixed <code>JavaLocalPattern</code> not matching on Lollipop <a href="https://github.com/square/leakcanary/pull/1524">#1524</a></li> |
| </ul> |
| <p>Many thanks to |
| <a href="https://github.com/Armaxis">@Armaxis</a>, |
| <a href="https://github.com/elihart">@elihart</a>, |
| <a href="https://github.com/emartynov">@emartynov</a>, |
| <a href="https://github.com/hmcgreevy-instil">@hmcgreevy-instil</a>, |
| <a href="https://github.com/pyricau">@pyricau</a> |
| for the contributions, bug reports and feature requests.</p> |
| <p>For more details, see the <a href="https://github.com/square/leakcanary/milestone/11">2.0-beta-3 Milestone</a> and the <a href="https://github.com/square/leakcanary/compare/v2.0-beta-2...v2.0-beta-3">full diff</a>.</p> |
| <h2 id="version-20-beta-2-2019-08-02">Version 2.0 Beta 2 (2019-08-02)<a class="headerlink" href="#version-20-beta-2-2019-08-02" title="Permanent link">¶</a></h2> |
| <ul> |
| <li>Fixed <em>Leak analysis failed: Object id not found in heap dump.</em> <a href="https://github.com/square/leakcanary/issues/1516">#1516</a></li> |
| <li>10x speed increase of hprof indexing on large heap dumps <a href="https://github.com/square/leakcanary/pull/1520">#1520</a></li> |
| </ul> |
| <p>Many thanks to |
| <a href="https://github.com/kolphi">@kolphi</a>, |
| <a href="https://github.com/pyricau">@pyricau</a>, |
| <a href="https://github.com/ZacSweers">@ZacSweers</a> |
| for the contributions, bug reports and feature requests.</p> |
| <p>For more details, see the <a href="https://github.com/square/leakcanary/milestone/10">2.0-beta-2 Milestone</a> and the <a href="https://github.com/square/leakcanary/compare/v2.0-beta-1...v2.0-beta-2">full diff</a>.</p> |
| <h2 id="version-20-beta-1-2019-07-30">Version 2.0 Beta 1 (2019-07-30)<a class="headerlink" href="#version-20-beta-1-2019-07-30" title="Permanent link">¶</a></h2> |
| <ul> |
| <li>New standalone library! <a href="../shark/">Shark</a> is the heap analyzer that powers LeakCanary 2, and it can run in any Java VM. It comes with a <a href="../shark/#shark-cli">CLI</a>: you can now run <code>shark-cli analyze-process com.example.myapp</code> from your computer.</li> |
| <li>New Heap Explorer directly on device! Open a Heap Analysis in LeakCanary, tap the options menu and select “Heap Explorer”. This is still experimental and not very user friendly, contributions welcome!</li> |
| <li><strong>Large API rewrite</strong> to improve usability. If you used the alpha with a customized configuration, there are breaking changes. Of note: LeakSentry became <a href="/leakcanary/api/leakcanary-object-watcher-android/leakcanary/-app-watcher/">AppWatcher</a>, RefWatcher became <a href="/leakcanary/api/leakcanary-object-watcher/leakcanary/-object-watcher/">ObjectWatcher</a>, AndroidExcludedRefs became <a href="/leakcanary/api/shark-android/shark/-android-reference-matchers/">AndroidReferenceMatchers</a>, AnalysisResultListener became <a href="/leakcanary/api/leakcanary-android-core/leakcanary/-on-heap-analyzed-listener/">OnHeapAnalyzedListener</a>, AndroidLeakTraceInspectors became <a href="/leakcanary/api/shark-android/shark/-android-object-inspectors/">AndroidObjectInspectors</a>.</li> |
| <li>The entire API surface is now documented and the documentation is available on this website: see the <strong>LeakCanary API</strong> tab at the top.</li> |
| <li>Removed the <strong>dependency on Android X</strong>. No more configuration issues! <a href="https://github.com/square/leakcanary/issues/1462">#1462</a></li> |
| <li>Added <strong>Proguard rules</strong> for LeakCanary and ObjectWatcher. <a href="https://github.com/square/leakcanary/pull/1500">#1500</a></li> |
| <li>Display LeakCanary version in the About screen. <a href="https://github.com/square/leakcanary/issues/1448">#1448</a></li> |
| <li>Bug fixes, new reference matchers and object inspectors</li> |
| </ul> |
| <p>Many thanks to |
| <a href="https://github.com/arctouch-carlosottoboni">@arctouch-carlosottoboni</a>, |
| <a href="https://github.com/jemaystermind">@jemaystermind</a>, |
| <a href="https://github.com/kushagrakumar27">@kushagrakumar27</a>, |
| <a href="https://github.com/pyricau">@pyricau</a>, |
| <a href="https://github.com/snkashis">@snkashis</a> |
| for the contributions, bug reports and feature requests.</p> |
| <p>For more details, see the <a href="https://github.com/square/leakcanary/milestone/9">2.0-beta-1 Milestone</a> and the <a href="https://github.com/square/leakcanary/compare/v2.0-alpha-3...v2.0-beta-1">full diff</a>.</p> |
| <h2 id="version-20-alpha-3-2019-07-04">Version 2.0 Alpha 3 (2019-07-04)<a class="headerlink" href="#version-20-alpha-3-2019-07-04" title="Permanent link">¶</a></h2> |
| <ul> |
| <li><a href="https://github.com/square/leakcanary/pull/1401">#1401</a> LeakCanary can now import all hprof files created from prior LeakCanary versions.</li> |
| <li><a href="https://github.com/square/leakcanary/pull/1414">#1414</a> New API: <code>RefWatcher.retainedInstances</code> which returns the instances that are currently considered retained.</li> |
| <li><a href="https://github.com/square/leakcanary/pull/1419">#1419</a> New APIs: <code>LeakCanary.Config.maxStoredHeapDumps</code> (default 7) and <code>LeakCanary.Config.requestWriteExternalStoragePermission</code> (default false). LeakCanary won’t ask for the external storage permission anymore by default.</li> |
| <li><a href="https://github.com/square/leakcanary/issues/1338">#1338</a> API change: <code>LeakCanary.Config.exclusionsFactory</code> replaced with <code>LeakCanary.Config.knownReferences</code> (simpler use), <code>LeakCanary.Config.leakInspectors</code> and <code>LeakCanary.Config.labelers</code> merged into <code>LeakCanary.Config.leakTraceInspectors</code> which provides access to the entire leak trace as well as a new graph oriented API that replaces the low level hprof parser API.</li> |
| <li><a href="https://github.com/square/leakcanary/issues/1382">#1382</a> LeakCanary now disables automatic heap dumping when running in AndroidX UI tests.</li> |
| <li><a href="https://github.com/square/leakcanary/pull/1424">#1424</a> API rename: <code>RefWatcher.hasRetainedReferences</code> => <code>RefWatcher.hasRetainedInstances</code>, <code>RefWatcher.retainedReferenceCount</code> => <code>RefWatcher.retainedInstanceCount</code>, <code>RefWatcher.hasWatchedReferences</code> => <code>RefWatcher.hasWatchedInstances</code>, <code>RefWatcher.removeKeysRetainedBeforeHeapDump</code> => <code>RefWatcher.removeInstancesRetainedBeforeHeapDump</code>, <code>RefWatcher.clearWatchedReferences</code> => <code>RefWatcher.clearWatchedInstances</code>.</li> |
| <li><a href="https://github.com/square/leakcanary/pull/1432">#1432</a> <a href="https://github.com/square/leakcanary/pull/1438">#1438</a> <a href="https://github.com/square/leakcanary/pull/1440">#1440</a> New “won’t fix” leaks and leak trace inspectors</li> |
| <li><a href="https://github.com/square/leakcanary/issues/1374">#1374</a> <a href="https://github.com/square/leakcanary/issues/1364">#1364</a> <a href="https://github.com/square/leakcanary/issues/1366">#1366</a> <a href="https://github.com/square/leakcanary/issues/1417">#1417</a> <a href="https://github.com/square/leakcanary/issues/#1399">#1399</a> <a href="https://github.com/square/leakcanary/issues/1416">#1416</a> <a href="https://github.com/square/leakcanary/issues/1407">#1407</a> <a href="https://github.com/square/leakcanary/issues/1427">#1427</a> <a href="https://github.com/square/leakcanary/issues/1385">#1385</a> Bug and crash fixes</li> |
| </ul> |
| <p>Many thanks to |
| <a href="https://github.com/1step2hell">@1step2hell</a>, |
| <a href="https://github.com/afollestad">@afollestad</a>, |
| <a href="https://github.com/ansman">@ansman</a>, |
| <a href="https://github.com/bjdodson">@bjdodson</a>, |
| <a href="https://github.com/BraisGabin">@BraisGabin</a>, |
| <a href="https://github.com/EBfVince">@EBfVince</a>, |
| <a href="https://github.com/jaredsburrows">@jaredsburrows</a>, |
| <a href="https://github.com/pforhan">@pforhan</a>, |
| <a href="https://github.com/pyricau">@pyricau</a>, |
| <a href="https://github.com/tellypresence">@tellypresence</a>, |
| <a href="https://github.com/wiyarmir">@wiyarmir</a> |
| for the contributions, bug reports and feature requests.</p> |
| <p>For more details, see the <a href="https://github.com/square/leakcanary/milestone/8">2.0-alpha-3 Milestone</a> and the <a href="https://github.com/square/leakcanary/compare/v2.0-alpha-2...v2.0-alpha-3">full diff</a>.</p> |
| <h2 id="version-20-alpha-2-2019-05-21">Version 2.0 Alpha 2 (2019-05-21)<a class="headerlink" href="#version-20-alpha-2-2019-05-21" title="Permanent link">¶</a></h2> |
| <ul> |
| <li><a href="https://github.com/square/leakcanary/pull/1040">#1040</a> Import and analyze hprof files from other devices</li> |
| <li><a href="https://github.com/square/leakcanary/pull/1344">#1344</a> Computing retained size</li> |
| <li><a href="https://github.com/square/leakcanary/pull/1325">#1325</a> New notification showing current count of retained instances</li> |
| <li><a href="https://github.com/square/leakcanary/pull/1079">#1079</a> “Excluded” leaks have been renamed to “Won’t fix” leaks to clarify meaning.</li> |
| <li><a href="https://github.com/square/leakcanary/pull/1328">#1328</a> New leaks are called out in the UI.</li> |
| <li><a href="https://github.com/square/leakcanary/pull/1327">#1327</a> LeakSentry can be enabled / disabled and is automatically disabled in non debuggable builds.</li> |
| <li><a href="https://github.com/square/leakcanary/pull/1173">#1173</a> Experimental: now reporting leaks that only go through weak references (previously reported as “no path to instance”)</li> |
| <li><a href="https://github.com/square/leakcanary/pull/1339">#1339</a> Readded support for Thread name based exclusions</li> |
| <li><a href="https://github.com/square/leakcanary/pull/1312">#1312</a> Fixed bug causing LeakCanary to stop detecting leaks after the app is killed.</li> |
| <li><a href="https://github.com/square/leakcanary/pull/1310">#1310</a> <a href="https://github.com/square/leakcanary/pull/1313">#1313</a> <a href="https://github.com/square/leakcanary/pull/1314">#1314</a> <a href="https://github.com/square/leakcanary/pull/1340">#1340</a> <a href="https://github.com/square/leakcanary/pull/1337">#1337</a> Many API changes</li> |
| <li><a href="https://github.com/square/leakcanary/pull/1296">#1296</a> <a href="https://github.com/square/leakcanary/pull/1293">#1293</a> <a href="https://github.com/square/leakcanary/pull/1306">#1306</a> <a href="https://github.com/square/leakcanary/pull/1336">#1336</a> Fixed several crashes.</li> |
| </ul> |
| <p>Many thanks to |
| <a href="https://github.com/forrestbice">@forrestbice</a>, |
| <a href="https://github.com/Foso">@Foso</a>, |
| <a href="https://github.com/Goddchen">@Goddchen</a>, |
| <a href="https://github.com/marcosholgado">@marcosholgado</a>, |
| <a href="https://github.com/orionlee">@orionlee</a>, |
| <a href="https://github.com/pyricau">@pyricau</a>, |
| <a href="https://github.com/satoshun">@satoshun</a>, |
| <a href="https://github.com/ZacSweers">@ZacSweers</a> |
| for the contributions!</p> |
| <p>For more details, see the <a href="https://github.com/square/leakcanary/milestone/7">2.0-alpha-2 Milestone</a> and the <a href="https://github.com/square/leakcanary/compare/v2.0-alpha-1...v2.0-alpha-2">full diff</a>.</p> |
| <h2 id="version-20-alpha-1-2019-04-23">Version 2.0 Alpha 1 (2019-04-23)<a class="headerlink" href="#version-20-alpha-1-2019-04-23" title="Permanent link">¶</a></h2> |
| <p><img alt="logo" src="../images/logo-2.0-200px.png" /></p> |
| <ul> |
| <li>New <a href="https://github.com/square/leakcanary/wiki/FAQ#who-made-the-logo">logo</a>, thanks <a href="https://github.com/flickator">@flickator</a>!</li> |
| <li>Entirely rewritten to <strong>100% Kotlin</strong></li> |
| <li>Multiple leaks detected in one analysis<ul> |
| <li>The heap is dumped when the app goes in the background, or when a minimum of 5 leaks is reached in the foreground.</li> |
| </ul> |
| </li> |
| <li>Leak grouping<ul> |
| <li>Leaks that share similar causes are grouped in the UI.</li> |
| <li>New screens to see the list of groups and each group.</li> |
| <li>Improved leaktrace strings to highlight leak causes.</li> |
| <li>Leaks can be shared to Stack Overflow</li> |
| </ul> |
| </li> |
| <li>New library: <strong>LeakSentry</strong>.<ul> |
| <li>Detects when objects are leaking and triggers LeakCanary</li> |
| <li>Can be used independently in production, for instance to report the number of leaking instances on an OutOfMemoryError crash.</li> |
| </ul> |
| </li> |
| <li>New heap parser<ul> |
| <li>Uses <strong>90% less memory and 6 times</strong> faster than the prior heap parser.</li> |
| <li>Runs in the same process as the app on a low priority thread.</li> |
| <li>No more dependency on Perflib and TroveJ. New dependency on Okio.</li> |
| <li>The old parser is still available as <code>leakcanary-android-perflib</code> but will be removed after alpha.</li> |
| </ul> |
| </li> |
| <li>Labelers can add any string content to leak elements</li> |
| <li>0 code setup, just add the one debug dependency.</li> |
| <li>Simpler configuration options</li> |
| <li>Updated from support library to Android X</li> |
| </ul> |
| <p>Many thanks to |
| <a href="https://github.com/BraisGabin">@BraisGabin</a>, |
| <a href="https://github.com/colinmarsch">@colinmarsch</a>, |
| <a href="https://github.com/jrodbx">@jrodbx</a>, |
| <a href="https://github.com/flickator">@flickator</a>, |
| <a href="https://github.com/JakeWharton">@JakeWharton</a>, |
| <a href="https://github.com/pyricau">@pyricau</a>, |
| <a href="https://github.com/WhatsEmo">@WhatsEmo</a> |
| for the contributions!</p> |
| <p>For more details, see the <a href="https://github.com/square/leakcanary/milestone/6">2.0-alpha-1 Milestone</a> and the <a href="https://github.com/square/leakcanary/compare/v1.6.3...v2.0-alpha-1">full diff</a>.</p> |
| <h2 id="version-163-2019-01-10">Version 1.6.3 (2019-01-10)<a class="headerlink" href="#version-163-2019-01-10" title="Permanent link">¶</a></h2> |
| <ul> |
| <li><a href="https://github.com/square/leakcanary/issues/1163">#1163</a> Fixed leaks being incorrectly classified as “no leak” due to missed GC Roots.</li> |
| <li><a href="https://github.com/square/leakcanary/issues/1153">#1153</a> <code>LeakCanary.isInAnalyzerProcess</code> now correctly returns true in the analyzer process prior to any first leak (could be triggered by starting the leak result activity).</li> |
| <li><a href="https://github.com/square/leakcanary/issues/1158">#1158</a> Stopped enabling DisplayLeakActivity when not using DisplayLeakService.</li> |
| <li><a href="https://github.com/square/leakcanary/issues/1135">#1135</a> Fixed IndexOutOfBoundsException for leak traces of size 1.</li> |
| <li><a href="https://github.com/square/leakcanary/issues/1163">#1163</a> Keep “no leak” heap dumps.</li> |
| </ul> |
| <p>Many thanks to |
| <a href="https://github.com/KMaragh">@KMaragh</a>, |
| <a href="https://github.com/pyricau">@pyricau</a>, |
| <a href="https://github.com/SebRut">@SebRut</a> |
| for the code contributions!</p> |
| <p>For more details, see the <a href="https://github.com/square/leakcanary/milestone/5">1.6.3 Milestone</a> and the <a href="https://github.com/square/leakcanary/compare/v1.6.2...v1.6.3">full diff</a>.</p> |
| <h2 id="version-162-2018-10-16">Version 1.6.2 (2018-10-16)<a class="headerlink" href="#version-162-2018-10-16" title="Permanent link">¶</a></h2> |
| <ul> |
| <li><a href="https://github.com/square/leakcanary/issues/1067">#1067</a> Fixed TransactionTooLargeException crash (leak analysis would never complete).</li> |
| <li><a href="https://github.com/square/leakcanary/pull/1061">#1061</a> Detection of Fragment view leaks after Fragment#onDestroyView().</li> |
| <li><a href="https://github.com/square/leakcanary/pull/1076">#1076</a> Added the FOREGROUND_SERVICE permission for Android P.</li> |
| <li><a href="https://github.com/square/leakcanary/issues/1062">#1062</a> The LeakCanary toast now always shows correctly. It doesn’t show if there is no activity in foreground.</li> |
| <li><a href="https://github.com/square/leakcanary/issues/1115">#1115</a> Reenabled the DisplayLeakActivity icon on fresh installs.</li> |
| <li><a href="https://github.com/square/leakcanary/pull/1100">#1100</a> Added nullability annotations to improve Kotlin support.</li> |
| <li>Updates to excluded leaks (<a href="https://github.com/square/leakcanary/commits/v1.6.2/leakcanary-android/src/main/java/com/squareup/leakcanary/AndroidExcludedRefs.java">commits</a>).</li> |
| <li>Updates to reachability inspectors (<a href="https://github.com/square/leakcanary/commits/v1.6.2/leakcanary-android/src/main/java/com/squareup/leakcanary/AndroidReachabilityInspectors.java">commits</a>).</li> |
| </ul> |
| <p>Many thanks to |
| <a href="https://github.com/fractalwrench">@fractalwrench</a>, |
| <a href="https://github.com/ZacSweers">@ZacSweers</a>, |
| <a href="https://github.com/Goddchen">@Goddchen</a>, |
| <a href="https://github.com/igokoro">@igokoro</a>, |
| <a href="https://github.com/IlyaGulya">@IlyaGulya</a>, |
| <a href="https://github.com/JakeWharton">@JakeWharton</a>, |
| <a href="https://github.com/javmarina">@javmarina</a>, |
| <a href="https://github.com/jokermonn">@jokermonn</a>, |
| <a href="https://github.com/jrodbx">@jrodbx</a>, |
| <a href="https://github.com/Parseus">@Parseus</a>, |
| <a href="https://github.com/pyricau">@pyricau</a>, |
| <a href="https://github.com/scottkennedy">@scottkennedy</a> |
| for the code contributions!</p> |
| <h3 id="public-api-changes">Public API changes<a class="headerlink" href="#public-api-changes" title="Permanent link">¶</a></h3> |
| <ul> |
| <li>Subclasses of <code>AbstractAnalysisResultService</code> should now override <code>onHeapAnalyzed(@NonNull AnalyzedHeap analyzedHeap)</code> instead of <code>onHeapAnalyzed(@NonNull HeapDump heapDump, @NonNull AnalysisResult result)</code></li> |
| </ul> |
| <p>For more details, see the <a href="https://github.com/square/leakcanary/milestone/4">1.6.2 Milestone</a> and the <a href="https://github.com/square/leakcanary/compare/v1.6.1...v1.6.2">full diff</a>.</p> |
| <h2 id="version-161-2018-06-21">Version 1.6.1 (2018-06-21)<a class="headerlink" href="#version-161-2018-06-21" title="Permanent link">¶</a></h2> |
| <ul> |
| <li><a href="https://github.com/square/leakcanary/issues/727">#727</a> Improved leak analysis: LeakCanary now identifies and highlights the potential causes of the leak.</li> |
| <li><a href="https://github.com/square/leakcanary/issues/1011">#1011</a> We noticed that computing the retained heap size could take a long time, so it’s now optional and off by default.</li> |
| <li><a href="https://github.com/square/leakcanary/pull/633">#633</a> Support for detecting leaks in instrumentation tests (<a href="https://github.com/square/leakcanary/wiki/Customizing-LeakCanary#running-leakcanary-in-instrumentation-tests">see the wiki</a>).</li> |
| <li><a href="https://github.com/square/leakcanary/pull/985">#985</a> Ability to convert leak traces into stack traces for easy remote reporting (<a href="../uploading/">see the wiki</a>).</li> |
| <li><a href="https://github.com/square/leakcanary/issues/983">#983</a> Support for watching destroyed Fragments.</li> |
| <li><a href="https://github.com/square/leakcanary/issues/846">#846</a> LeakCanary now uses foreground services and displays a notification when the analysis is in progress. This also fixes crashes when analyzing in background on O+.</li> |
| <li>The LeakCanary icon (to start to DisplayLeakActivity) is now hidden by default, and only enabled after the first leak is found.</li> |
| <li><a href="https://github.com/square/leakcanary/issues/775">#775</a> Fixed crash when sharing heap dumps on O+ and added a dependency to the support-core-utils library.</li> |
| <li><a href="https://github.com/square/leakcanary/pull/930">#930</a> DisplayLeakActivity has a responsive icon.</li> |
| <li><a href="https://github.com/square/leakcanary/issues/685">#685</a> Stopped doing IO on main thread in DisplayLeakActivity (fixes StrictMode errors).</li> |
| <li><a href="https://github.com/square/leakcanary/pull/999">#999</a> Updated HAHA to 2.0.4, which uses Trove4j as an external dependency (from jcenter) instead of rebundling it. This is to clarify licences (Apache v2 vs LGPL 2.1).</li> |
| <li>Several bug and crash fixes.</li> |
| </ul> |
| <p>Many thanks to <a href="https://github.com/AdityaAnand1">@AdityaAnand1</a>, <a href="https://github.com/alhah">@alhah</a>, <a href="https://github.com/christxph">@christxph</a>, <a href="https://github.com/csoon03">@csoon03</a>, <a href="https://github.com/daqi">@daqi</a>, <a href="https://github.com/JakeWharton">@JakeWharton</a>, <a href="https://github.com/jankovd">@jankovd</a>, <a href="https://github.com/jrodbx">@jrodbx</a>, <a href="https://github.com/kurtisnelson">@kurtisnelson</a>, <a href="https://github.com/NightlyNexus">@NightlyNexus</a>, <a href="https://github.com/pyricau">@pyricau</a>, <a href="https://github.com/SalvatoreT">@SalvatoreT</a>, <a href="https://github.com/shmuelr">@shmuelr</a>, <a href="https://github.com/tokou">@tokou</a>, <a href="https://github.com/xueqiushi">@xueqiushi</a> |
| for the code contributions!</p> |
| <p>Note: we made a 1.6 release but quickly followed up with 1.6.1 due to <a href="https://github.com/square/leakcanary/issues/1058">#1058</a>.</p> |
| <h3 id="public-api-changes_1">Public API changes<a class="headerlink" href="#public-api-changes_1" title="Permanent link">¶</a></h3> |
| <ul> |
| <li>The installed ref watcher singleton is now available via <code>LeakCanary.installedRefWatcher()</code></li> |
| <li><code>AnalysisResult.leakTraceAsFakeException()</code> returns an exception that can be used to report and group leak traces to a tool like Bugsnag or Crashlytics.</li> |
| <li>New <code>InstrumentationLeakDetector</code> and <code>FailTestOnLeakRunListener</code> APIs for detecting leaks in instrumentation tests.</li> |
| <li>New <code>Reachability.Inspector</code> and <code>RefWatcherBuilder.stethoscopeClasses()</code> API to establish reachability and help identify leak causes.</li> |
| <li>Watching activities can be disabled with <code>AndroidRefWatcherBuilder.watchActivities(false)</code>, watching fragments can be disabled with <code>AndroidRefWatcherBuilder.watchFragments(false)</code></li> |
| <li><code>LeakCanary.setDisplayLeakActivityDirectoryProvider()</code> is deprecated and replaced with <code>LeakCanary.setLeakDirectoryProvider()</code></li> |
| <li>New <code>RefWatcherBuilder.computeRetainedHeapSize()</code> API to enable the computing of the retained heap size (off by default).</li> |
| </ul> |
| <p>For more details, see the <a href="https://github.com/square/leakcanary/milestone/3">1.6.1 Milestone</a> and the <a href="https://github.com/square/leakcanary/compare/v1.5.4...v1.6.1">full diff</a>.</p> |
| <h2 id="version-154-2017-09-22">Version 1.5.4 <em>(2017-09-22)</em><a class="headerlink" href="#version-154-2017-09-22" title="Permanent link">¶</a></h2> |
| <ul> |
| <li>Restore Java 7 compatibility in leakcanary-watcher</li> |
| </ul> |
| <h2 id="version-153-2017-09-17">Version 1.5.3 <em>(2017-09-17)</em><a class="headerlink" href="#version-153-2017-09-17" title="Permanent link">¶</a></h2> |
| <ul> |
| <li>Fix broken 1.5.2 <a href="https://github.com/square/leakcanary/issues/815">build</a></li> |
| <li>Convert leakcanary-watcher from Android library to Java library</li> |
| <li>Disable finish animations in RequestStoragePermissionActivity</li> |
| <li>Corrected README sample for Robolectric tests</li> |
| </ul> |
| <p>For more details, see the <a href="https://github.com/square/leakcanary/compare/v1.5.2...v1.5.3">full diff</a>.</p> |
| <h2 id="version-152-2017-08-09">Version 1.5.2 <em>(2017-08-09)</em><a class="headerlink" href="#version-152-2017-08-09" title="Permanent link">¶</a></h2> |
| <ul> |
| <li>New excluded leaks</li> |
| <li>Move Leakcanary UI into leak analyzer process</li> |
| <li>Ignore computing retained sizes for bitmaps on O+</li> |
| <li>Add notification channel for persistent messages on O+</li> |
| <li>Exclude permission activity from recents menu</li> |
| <li>Updated README and sample for handling Robolectric tests</li> |
| </ul> |
| <p>For more details, see the <a href="https://github.com/square/leakcanary/compare/v1.5.1...v1.5.2">full diff</a>.</p> |
| <h2 id="version-151-2017-04-25">Version 1.5.1 <em>(2017-04-25)</em><a class="headerlink" href="#version-151-2017-04-25" title="Permanent link">¶</a></h2> |
| <ul> |
| <li>New excluded leaks</li> |
| <li>Fix java.util.MissingFormatArgumentException in DisplayLeakService</li> |
| <li>Separate task affinities for different apps</li> |
| <li>Bump minSdk to 14</li> |
| <li>Fix HahaHelper for O Preview</li> |
| </ul> |
| <p>For more details, see the <a href="https://github.com/square/leakcanary/compare/v1.5...v1.5.1">full diff</a>.</p> |
| <h2 id="version-15-2016-09-28">Version 1.5 <em>(2016-09-28)</em><a class="headerlink" href="#version-15-2016-09-28" title="Permanent link">¶</a></h2> |
| <ul> |
| <li>New excluded leaks</li> |
| <li>Added <code>LeakCanary.isInAnalyzerProcess()</code> to the no-op jar</li> |
| <li>Fixed several file access issues:<ul> |
| <li>No more cleanup on startup, we rotate the heap dump files on every new heap dump.</li> |
| <li>LeakCanary now falls back to the app directory until it can write to the external storage.</li> |
| </ul> |
| </li> |
| <li>Leak notifications now each use a distinct notification instead of erasing each other.</li> |
| <li>If LeakCanary can’t perform a heap dump for any reason (e.g. analysis in progress, debugger attached), it retries later with an exponential backoff.</li> |
| <li>Added confirmation dialog when user deletes all leaks.</li> |
| <li>Replace the two LeakCanary configuration methods with a builder that provides more flexibility, see <code>LeakCanary.refWatcher()</code>.</li> |
| </ul> |
| <p>For more details, see the <a href="https://github.com/square/leakcanary/compare/v1.4...v1.5">full diff</a>.</p> |
| <h3 id="public-api-changes_2">Public API changes<a class="headerlink" href="#public-api-changes_2" title="Permanent link">¶</a></h3> |
| <ul> |
| <li>New <code>HeapAnalyzer.findTrackedReferences()</code> method for headless analysis when you have no context on what leaked.</li> |
| <li>Added <code>LeakCanary.isInAnalyzerProcess()</code> to the no-op jar</li> |
| <li>Added <code>LeakCanary.refWatcher()</code> which returns an <code>AndroidRefWatcherBuilder</code> that extends <code>RefWatcherBuilder</code> and lets you fully customize the <code>RefWatcher</code> instance.</li> |
| <li>Removed <code>LeakCanary.install(Application, Class)</code> and <code>LeakCanary.androidWatcher(Context, HeapDump.Listener, ExcludedRefs)</code>.</li> |
| <li>Removed <code>R.integer.leak_canary_max_stored_leaks</code> and <code>R.integer.leak_canary_watch_delay_millis</code>, those can now be set via <code>LeakCanary.refWatcher()</code>.</li> |
| <li>Updated the <code>LeakDirectoryProvider</code> API to centralize all file related responsibilities.</li> |
| <li><code>RefWatcher</code> is now constructed with a <code>WatchExecutor</code> which executes a <code>Retryable</code>, instead of an <code>Executor</code> that executes a <code>Runnable</code>.</li> |
| <li><code>HeapDumper.NO_DUMP</code> was renamed <code>HeapDumper.RETRY_LATER</code></li> |
| </ul> |
| <h2 id="version-14-2016-09-11">Version 1.4 <em>(2016-09-11)</em><a class="headerlink" href="#version-14-2016-09-11" title="Permanent link">¶</a></h2> |
| <ul> |
| <li>Fix false negative where GC root is of type android.os.Binder <a href="https://github.com/square/leakcanary/issues/482">#482</a></li> |
| <li>Update HAHA to 2.0.3; clear compiler warnings <a href="https://github.com/square/leakcanary/issues/563">#563</a></li> |
| <li>Correct some mistakes in German translation <a href="https://github.com/square/leakcanary/pull/516">#516</a></li> |
| <li>Don’t loop when storage permission denied <a href="https://github.com/square/leakcanary/issues/422">#422</a></li> |
| <li>Remove old references to “__” prefixed resources <a href="https://github.com/square/leakcanary/pull/477">#477</a></li> |
| <li>Fix permission crash for DisplayLeakActivity on M <a href="https://github.com/square/leakcanary/issues/382">#382</a></li> |
| <li>Fix NPE when thread name not found in heap dump <a href="https://github.com/square/leakcanary/issues/417">#417</a></li> |
| <li>Add version info to stacktrace <a href="https://github.com/square/leakcanary/issues/473">#473</a></li> |
| </ul> |
| <h2 id="version-14-beta2-2016-03-23">Version 1.4-beta2 <em>(2016-03-23)</em><a class="headerlink" href="#version-14-beta2-2016-03-23" title="Permanent link">¶</a></h2> |
| <ul> |
| <li>Add reason for ignoring to analysis result <a href="https://github.com/square/leakcanary/issues/365">#365</a>.</li> |
| <li>Lower memory usage when parsing heap dumps on M <a href="https://github.com/square/leakcanary/issues/223">#223</a>.</li> |
| <li>Fix NPE in LeakCanaryInternals.isInServiceProcess() <a href="https://github.com/square/leakcanary/issues/449">#449</a>.</li> |
| <li>New ignored Android SDK leaks <a href="https://github.com/square/leakcanary/issues/297">#297</a>,<a href="https://github.com/square/leakcanary/issues/322">#322</a>.</li> |
| <li>Use leakcanary-android-no-op in test builds <a href="https://github.com/square/leakcanary/issues/143">#143</a>.</li> |
| <li>Fixes to allow LeakCanary to work with ProGuard <a href="https://github.com/square/leakcanary/pull/398">#398</a>.</li> |
| <li>Optimize png assets <a href="https://github.com/square/leakcanary/pull/406">#406</a>.</li> |
| <li>Fix delete button not working on error views <a href="https://github.com/square/leakcanary/pull/408">#408</a>.</li> |
| <li>Add German translation <a href="https://github.com/square/leakcanary/pull/437">#437</a>.</li> |
| </ul> |
| <h2 id="version-14-beta1-2016-01-08">Version 1.4-beta1 <em>(2016-01-08)</em><a class="headerlink" href="#version-14-beta1-2016-01-08" title="Permanent link">¶</a></h2> |
| <ul> |
| <li>Switched to <a href="https://github.com/square/haha/blob/master/CHANGELOG.md#version-202-2015-07-20">HAHA 2.0.2</a> with uses Perflib instead of MAT under the hood <a href="https://github.com/square/leakcanary/pull/219">#219</a>. This fixes crashes and improves speed a lot.</li> |
| <li>We can now parse Android M heap dumps <a href="https://github.com/square/leakcanary/issues/267">#267</a>, although there are still memory issues (see <a href="https://github.com/square/leakcanary/issues/223">#223</a>).</li> |
| <li>Excluded leaks are now reported as well and available in the display leak activity.</li> |
| <li>Added ProGuard configuration for <a href="https://github.com/square/leakcanary/issues/132">#132</a>.</li> |
| <li>Many new ignored Android SDK leaks.</li> |
| <li>Added excluded leaks to text report <a href="https://github.com/square/leakcanary/issues/119">#119</a>.</li> |
| <li>Added LeakCanary SHA to text report <a href="https://github.com/square/leakcanary/issues/120">#120</a>.</li> |
| <li>Added CanaryLog API to replace the logger: <a href="https://github.com/square/leakcanary/issues/201">#201</a>.</li> |
| <li>Renamed all resources to begin with <code>leak_canary_</code> instead of <code>__leak_canary</code><a href="https://github.com/square/leakcanary/pull/161">#161</a></li> |
| <li>No crash when heap dump fails <a href="https://github.com/square/leakcanary/issues/226">#226</a>.</li> |
| <li>Add retained size to leak reports <a href="https://github.com/square/leakcanary/issues/162">#162</a>.</li> |
| </ul> |
| <h3 id="public-api-changes_3">Public API changes<a class="headerlink" href="#public-api-changes_3" title="Permanent link">¶</a></h3> |
| <ul> |
| <li>AnalysisResult.failure is now a <code>Throwable</code> instead of an <code>Exception</code>. Main goal is to catch and correctly report OOMs while parsing.</li> |
| <li>Added ARRAY_ENTRY to LeakTraceElement.Type for references through array entries.</li> |
| <li>Renamed <code>ExcludedRefs</code> fields.</li> |
| <li>Each <code>ExcludedRef</code> entry can now be ignored entirely or “kept only if no other path”.</li> |
| <li>Added support for ignoring all fields (static and non static) for a given class.</li> |
| </ul> |
| <h2 id="version-131-2015-05-16">Version 1.3.1 <em>(2015-05-16)</em><a class="headerlink" href="#version-131-2015-05-16" title="Permanent link">¶</a></h2> |
| <ul> |
| <li>Heap dumps and analysis results are now saved on the sd card: <a href="https://github.com/square/leakcanary/issues/21">#21</a>.</li> |
| <li><code>ExcludedRef</code> and <code>AndroidExcludedRefs</code> are customizable: <a href="https://github.com/square/leakcanary/issues/12">#12</a> <a href="https://github.com/square/leakcanary/issues/73">#73</a>.</li> |
| <li>7 new ignored Android SDK leaks: <a href="https://github.com/square/leakcanary/issues/1">#1</a> <a href="https://github.com/square/leakcanary/issues/4">#4</a> <a href="https://github.com/square/leakcanary/issues/32">#32</a> <a href="https://github.com/square/leakcanary/pull/89">#89</a> <a href="https://github.com/square/leakcanary/pull/82">#82</a> <a href="https://github.com/square/leakcanary/pull/97">#97</a>.</li> |
| <li>Fixed 3 crashes in LeakCanary: <a href="https://github.com/square/leakcanary/issues/37">#37</a> <a href="https://github.com/square/leakcanary/issues/46">#46</a> <a href="https://github.com/square/leakcanary/issues/66">#66</a>.</li> |
| <li>Fixed StrictMode thread policy violations: <a href="https://github.com/square/leakcanary/issues/15">#15</a>.</li> |
| <li>Updated <code>minSdkVersion</code> from <code>9</code> to <code>8</code>: <a href="https://github.com/square/leakcanary/issues/57">#57</a>.</li> |
| <li>Added LeakCanary version name to <code>LeakCanary.leakInfo()</code>: <a href="https://github.com/square/leakcanary/issues/49">#49</a>.</li> |
| <li><code>leakcanary-android-no-op</code> is lighter, it does not depend on <code>leakcanary-watcher</code> anymore, only 2 classes now: <a href="https://github.com/square/leakcanary/issues/74">#74</a>.</li> |
| <li>Adding field state details to the text leak trace.</li> |
| <li>A Toast is displayed while the heap dump is in progress to warn that the UI will freeze: <a href="https://github.com/square/leakcanary/issues/49">#20</a>. You can customize the toast by providing your own layout named <code>__leak_canary_heap_dump_toast.xml</code> (e.g. you could make it an empty layout).</li> |
| <li>If the analysis fails, the result and heap dump are kept so that it can be reported to LeakCanary: <a href="https://github.com/square/leakcanary/issues/102">#102</a>.</li> |
| <li>Update to HAHA 1.3 to fix a 2 crashes <a href="https://github.com/square/leakcanary/issues/3">#3</a> <a href="https://github.com/square/leakcanary/issues/46">46</a></li> |
| </ul> |
| <h3 id="public-api-changes_4">Public API changes<a class="headerlink" href="#public-api-changes_4" title="Permanent link">¶</a></h3> |
| <ul> |
| <li>When upgrading from 1.3 to 1.3.1, previously saved heap dumps will not be readable any more, but they won’t be removed from the app directory. You should probably uninstall your app.</li> |
| <li>Added <code>android.permission.WRITE_EXTERNAL_STORAGE</code> to <code>leakcanary-android</code> artifact.</li> |
| <li><code>LeakCanary.androidWatcher()</code> parameter types have changed (+ExcludedRefs).</li> |
| <li><code>LeakCanary.leakInfo()</code> parameter types have changed (+boolean)</li> |
| <li><code>ExcludedRef</code> is now serializable and immutable, instances can be created using <code>ExcludedRef.Builder</code>.</li> |
| <li><code>ExcludedRef</code> is available in <code>HeapDump</code></li> |
| <li><code>AndroidExcludedRefs</code> is an enum, you can now pick the leaks you want to ignore in <code>AndroidExcludedRefs</code> by creating an <code>EnumSet</code> and calling <code>AndroidExcludedRefs.createBuilder()</code>.</li> |
| <li><code>AndroidExcludedRefs.createAppDefaults()</code> & <code>AndroidExcludedRefs.createAndroidDefaults()</code> return a <code>ExcludedRef.Builder</code>.</li> |
| <li><code>ExcludedRef</code> moved from <code>leakcanary-analyzer</code> to <code>leakcanary-watcher</code></li> |
| </ul> |
| <h2 id="version-13-2015-05-08">Version 1.3 <em>(2015-05-08)</em><a class="headerlink" href="#version-13-2015-05-08" title="Permanent link">¶</a></h2> |
| <p>Initial release.</p> |
| <h3 id="dependencies">Dependencies<a class="headerlink" href="#dependencies" title="Permanent link">¶</a></h3> |
| |
| |
| </article> |
| </div> |
| |
| |
| </div> |
| |
| </main> |
| |
| <footer class="md-footer"> |
| |
| <div class="md-footer-meta md-typeset"> |
| <div class="md-footer-meta__inner md-grid"> |
| <div class="md-copyright"> |
| |
| <div class="md-copyright__highlight"> |
| Copyright © 2015 Square, Inc. |
| </div> |
| |
| |
| Made with |
| <a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener"> |
| Material for MkDocs |
| </a> |
| |
| </div> |
| |
| <div class="md-social"> |
| |
| |
| |
| |
| |
| |
| |
| |
| <a href="https://square.github.io/" target="_blank" rel="noopener" title="square.github.io" class="md-social__link"> |
| <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 480 512"><!--! Font Awesome Free 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M186.1 328.7c0 20.9-10.9 55.1-36.7 55.1s-36.7-34.2-36.7-55.1 10.9-55.1 36.7-55.1 36.7 34.2 36.7 55.1zM480 278.2c0 31.9-3.2 65.7-17.5 95-37.9 76.6-142.1 74.8-216.7 74.8-75.8 0-186.2 2.7-225.6-74.8-14.6-29-20.2-63.1-20.2-95 0-41.9 13.9-81.5 41.5-113.6-5.2-15.8-7.7-32.4-7.7-48.8 0-21.5 4.9-32.3 14.6-51.8 45.3 0 74.3 9 108.8 36 29-6.9 58.8-10 88.7-10 27 0 54.2 2.9 80.4 9.2 34-26.7 63-35.2 107.8-35.2 9.8 19.5 14.6 30.3 14.6 51.8 0 16.4-2.6 32.7-7.7 48.2 27.5 32.4 39 72.3 39 114.2zm-64.3 50.5c0-43.9-26.7-82.6-73.5-82.6-18.9 0-37 3.4-56 6-14.9 2.3-29.8 3.2-45.1 3.2-15.2 0-30.1-.9-45.1-3.2-18.7-2.6-37-6-56-6-46.8 0-73.5 38.7-73.5 82.6 0 87.8 80.4 101.3 150.4 101.3h48.2c70.3 0 150.6-13.4 150.6-101.3zm-82.6-55.1c-25.8 0-36.7 34.2-36.7 55.1s10.9 55.1 36.7 55.1 36.7-34.2 36.7-55.1-10.9-55.1-36.7-55.1z"/></svg> |
| </a> |
| |
| |
| |
| |
| |
| |
| |
| |
| <a href="https://twitter.com/Piwai" target="_blank" rel="noopener" title="twitter.com" class="md-social__link"> |
| <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"/></svg> |
| </a> |
| |
| |
| |
| |
| |
| |
| |
| |
| <a href="https://stackoverflow.com/questions/tagged/leakcanary?sort=active" target="_blank" rel="noopener" title="stackoverflow.com" class="md-social__link"> |
| <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><!--! Font Awesome Free 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M290.7 311 95 269.7 86.8 309l195.7 41zm51-87L188.2 95.7l-25.5 30.8 153.5 128.3zm-31.2 39.7L129.2 179l-16.7 36.5L293.7 300zM262 32l-32 24 119.3 160.3 32-24zm20.5 328h-200v39.7h200zm39.7 80H42.7V320h-40v160h359.5V320h-40z"/></svg> |
| </a> |
| |
| |
| |
| |
| |
| |
| |
| |
| <a href="https://www.linkedin.com/company/joinsquare/" target="_blank" rel="noopener" title="www.linkedin.com" class="md-social__link"> |
| <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.3.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M416 32H31.9C14.3 32 0 46.5 0 64.3v383.4C0 465.5 14.3 480 31.9 480H416c17.6 0 32-14.5 32-32.3V64.3c0-17.8-14.4-32.3-32-32.3zM135.4 416H69V202.2h66.5V416zm-33.2-243c-21.3 0-38.5-17.3-38.5-38.5S80.9 96 102.2 96c21.2 0 38.5 17.3 38.5 38.5 0 21.3-17.2 38.5-38.5 38.5zm282.1 243h-66.4V312c0-24.8-.5-56.7-34.5-56.7-34.6 0-39.9 27-39.9 54.9V416h-66.4V202.2h63.7v29.2h.9c8.9-16.8 30.6-34.5 62.9-34.5 67.2 0 79.7 44.3 79.7 101.9V416z"/></svg> |
| </a> |
| |
| </div> |
| |
| </div> |
| </div> |
| </footer> |
| |
| </div> |
| <div class="md-dialog" data-md-component="dialog"> |
| <div class="md-dialog__inner md-typeset"></div> |
| </div> |
| |
| <script id="__config" type="application/json">{"base": "..", "features": ["tabs"], "search": "../assets/javascripts/workers/search.208ed371.min.js", "translations": {"clipboard.copied": "Copied to clipboard", "clipboard.copy": "Copy to clipboard", "search.result.more.one": "1 more on this page", "search.result.more.other": "# more on this page", "search.result.none": "No matching documents", "search.result.one": "1 matching document", "search.result.other": "# matching documents", "search.result.placeholder": "Type to start searching", "search.result.term.missing": "Missing", "select.version": "Select version"}}</script> |
| |
| |
| <script src="../assets/javascripts/bundle.efa0ade1.min.js"></script> |
| |
| |
| </body> |
| </html> |