Git Product home page Git Product logo

leak_detector's Introduction

中文文档

leak_detector

flutter Memory leak detection tool

Usage

initialize

In order to prevent the underlying library vm service from crashing, please call before adding the memory leak detection object:

LeakDetector().init(maxRetainingPath: 300); //maxRetainingPath default is 300

Enabling leak detection will reduce performance, and Full GC may drop frames on the page. Initialized by assert in the plugin, so you don't need to turn it off when build on release mode.

Detect

Add LeakNavigatorObserver to navigatorObservers in MaterialApp, it will automatically detect whether there is a memory leak in the page's Widget and its corresponding Element object. If page's Widget is a StatefulWidget, it will also be automatically checked Its corresponding State.

import 'package:leak_detector/leak_detector.dart';

@override
Widget build(BuildContext context) {
  return MaterialApp(
    navigatorObservers: [
      //used the LeakNavigatorObserver
      LeakNavigatorObserver(
        shouldCheck: (route) {
          return route.settings.name != null && route.settings.name != '/';
        },
      ),
    ],
  );
}

Get leaked information

LeakDetector().onLeakedStream can register your listener, and notify the object's reference chain after detecting a memory leak. LeakDetector().onEventStream can monitor internal time notifications, such as start Gc, end Gc, etc.

A preview page of the reference chain is provided. You only need to add the following code. Note that the Bulid Context must be able to obtain theNavigatorState:

import 'package:leak_detector/leak_detector.dart';

//show preview page
LeakDetector().onLeakedStream.listen((LeakedInfo info) {
  //print to console
  info.retainingPath.forEach((node) => print(node));
  //show preview page
  showLeakedInfoPage(navigatorKey.currentContext, info);
});

Preview page display:

It contains the class information of the reference chain node, the referenced attribute information, the source code of the attribute declaration, and the location of the source code (line number: column number).

Get memory leak recording

import 'package:leak_detector/leak_detector.dart';

getLeakedRecording().then((List<LeakedInfo> infoList) {
  showLeakedInfoListPage(navigatorKey.currentContext, infoList);
});

*Cannot connect to vm_service on real mobile devices

The VM service allows for an extended feature set via the Dart Development Service (DDS) that forward all core VM service RPCs described in this document to the true VM service.

So when we connect to the computer to run, the DDS on the computer will first connect to the vm_service on our mobile end, causing our leak_detector plugin to fail to connect to the vm_service again.

There are two solutions:

  • After the run is complete, disconnect from the computer, and then it is best to restart the app.

    If the completed test package is installed on the mobile phone, the above problem does not exist, so this method is suitable for use by testers.

  • Add the --disable-dds parameter after flutter run to turn off the DDS. After testing, this will not cause any impact on debugging

    It can be configured as follows in Android Studio.

After Pull Request #80900 is merged, --disable-dds was renamed to --no-dds

image

image

leak_detector's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

leak_detector's Issues

貌似新版本运行example已经不会报内存泄露了?

Performing hot restart...
Syncing files to device iPhone 15 Pro...
Restarted application in 954ms.
flutter: DetectorEventType.addObject, /p1(78023448)
flutter: DetectorEventType.addObject, /p1(78023448)
flutter: DetectorEventType.check, /p1(78023448)
flutter: DetectorEventType.startGC, null
flutter: DetectorEventType.endGc, null

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel beta, 3.16.0-0.3.pre, on macOS 14.0 23A344 darwin-x64, locale zh-Hans-CN)
[✓] Android toolchain - develop for Android devices (Android SDK version 32.0.0-rc1)
[✓] Xcode - develop for iOS and macOS (Xcode 15.0.1)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2022.3)

请教一下如何看结果

谢谢大佬提供这个轮子,能运行监控到内存泄漏。但看不懂结果,哪个才是泄漏的地方,要看哪里呀?

Plugin with id 'kotlin-android' not found

我看了下,是android/build.gradle 中,缺少了kotlin的插件依赖,这个能加上嘛,发布个新版本。

buildscript {
    ext.kotlin_version = '1.3.50'
    repositories {
        google()
        jcenter()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:4.1.0'
        // 缺少这句依赖
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

getObjectInstanceById error:[Sentinel kind: Collected, valueAsString: <collected>] from getObject()

D/EGL_emulation(13027): app_time_stats: avg=1523.36ms min=1.86ms max=13548.83ms count=9
D/EGL_emulation(13027): app_time_stats: avg=162.87ms min=1.61ms max=1572.26ms count=10
I/flutter (13027): DetectorEventType.addObject, /p2(695009372)
I/flutter (13027): DetectorEventType.addObject, /p2(695009372)
I/flutter (13027): DetectorEventType.addObject, /p2(695009372)
D/EGL_emulation(13027): app_time_stats: avg=187.87ms min=1.19ms max=3410.00ms count=19
I/flutter (13027): DetectorEventType.check, /p2(695009372)
I/flutter (13027): DetectorEventType.startGC, null
I/flutter (13027): DetectorEventType.endGc, null
I/flutter (13027): getObjectInstanceById error:[Sentinel kind: Collected, valueAsString: ] from getObject()
I/flutter (13027): getObjectInstanceById error:[Sentinel kind: Collected, valueAsString: ] from getObject()
I/flutter (13027): getObjectInstanceById error:[Sentinel kind: Collected, valueAsString: ] from getObject()
D/TrafficStats(13027): tagSocket(83) with statsTag=0x8001, statsUid=-1
D/TrafficStats(13027): tagSocket(83) with statsTag=0x8001, statsUid=-1

leak_detector: ^1.1.0

Flutter (Channel stable, 3.13.9, on macOS 13.4.1 22F770820d darwin-arm64, locale zh-Hans-CN)

Upgrade kotlin:kotlin-gradle-plugin

I've tried to add this beautiful and needed library to our project but encountered following error.

FAILURE: Build failed with an exception.
* What went wrong:
The Android Gradle plugin supports only Kotlin Gradle plugin version 1.5.20 and higher.
The following dependencies do not satisfy the required version:
project ':leak_detector' -> org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.50

Would it be possible to upgrade this project to use Kotlin Gradle plugin version 1.5.20 and higher?
Thank you so much.

Fluter 3.3: Need to update Update vm_service dependency

To update to flutter 3.3.2 it throws me this error:

Because every version of flutter_driver from sdk depends on vm_service 9.0.0 and leak_detector 1.0.1+4 depends on vm_service ^8.1.0, flutter_driver from sdk is incompatible with leak_detector 1.0.1+4.
So, because client depends on both leak_detector 1.0.1+4 and flutter_driver from sdk, version solving failed.
pub get failed (1; So, because client depends on both leak_detector 1.0.1+4 and flutter_driver from sdk, version solving failed.)

偶先图片组件泄露堆栈。

我也写了个检测工具,原理跟楼主一样。不知道楼主见过这种偶现堆栈没,图片被_NativeSocket引用,这种很久都不释放,导致误报,影响开发人员判断, 这个泄露从官方observtory里面也能看到。

 retained by _owner@1318392247 of _DebugSize 
retained by size of ImageConfiguration retained by Context(7) 
retained by Closure()(function = ImageProvider._createErrorHandlerAndKey.) 
retained by function of _ZoneFunction
 retained by _handleUncaughtError@4048458 of _CustomZone retained by Context(2)
 retained by Closure()(function = _CustomZone.bindBinaryCallbackGuarded.)
 retained by _List retained by eventHandlers of _NativeSocket

Undefined symbols for architecture arm64:

Undefined symbols for architecture arm64:
"value witness table for Builtin.UnknownObject", referenced from:
full type metadata for leak_detector.SwiftLeakDetectorPlugin in libleak_detector.a(SwiftLeakDetectorPlugin.o)
"_swift_FORCE_LOAD$_swiftCompatibilityDynamicReplacements", referenced from:
_swift_FORCE_LOAD$swiftCompatibilityDynamicReplacements$_leak_detector in libleak_detector.a(SwiftLeakDetectorPlugin.o)
(maybe you meant: _swift_FORCE_LOAD$swiftCompatibilityDynamicReplacements$_leak_detector)
"_swift_FORCE_LOAD$_swiftCompatibility51", referenced from:
_swift_FORCE_LOAD$swiftCompatibility51$_leak_detector in libleak_detector.a(SwiftLeakDetectorPlugin.o)
(maybe you meant: _swift_FORCE_LOAD$swiftCompatibility51$_leak_detector)
"_swift_FORCE_LOAD$_swiftCompatibility50", referenced from:
_swift_FORCE_LOAD$swiftCompatibility50$_leak_detector in libleak_detector.a(SwiftLeakDetectorPlugin.o)
(maybe you meant: _swift_FORCE_LOAD$swiftCompatibility50$_leak_detector)
"_swift_FORCE_LOAD$_swiftQuartzCore", referenced from:
_swift_FORCE_LOAD$swiftQuartzCore$_leak_detector in libleak_detector.a(SwiftLeakDetectorPlugin.o)
(maybe you meant: _swift_FORCE_LOAD$swiftQuartzCore$_leak_detector)
"_swift_FORCE_LOAD$_swiftCoreImage", referenced from:
_swift_FORCE_LOAD$swiftCoreImage$_leak_detector in libleak_detector.a(SwiftLeakDetectorPlugin.o)
(maybe you meant: _swift_FORCE_LOAD$swiftCoreImage$_leak_detector)
"_swift_FORCE_LOAD$_swiftCoreGraphics", referenced from:
_swift_FORCE_LOAD$swiftCoreGraphics$_leak_detector in libleak_detector.a(SwiftLeakDetectorPlugin.o)
(maybe you meant: _swift_FORCE_LOAD$swiftCoreGraphics$_leak_detector)
"_swift_FORCE_LOAD$_swiftCoreFoundation", referenced from:
_swift_FORCE_LOAD$swiftCoreFoundation$_leak_detector in libleak_detector.a(SwiftLeakDetectorPlugin.o)
(maybe you meant: _swift_FORCE_LOAD$swiftCoreFoundation$_leak_detector)
"_swift_getObjectType", referenced from:
static leak_detector.SwiftLeakDetectorPlugin.register(with: __C.FlutterPluginRegistrar) -> () in libleak_detector.a(SwiftLeakDetectorPlugin.o)
"_swift_FORCE_LOAD$_swiftUIKit", referenced from:
_swift_FORCE_LOAD$swiftUIKit$_leak_detector in libleak_detector.a(SwiftLeakDetectorPlugin.o)
(maybe you meant: _swift_FORCE_LOAD$swiftUIKit$_leak_detector)
"swift_allocObject", referenced from:
@objc leak_detector.SwiftLeakDetectorPlugin.handle(
: __C.FlutterMethodCall, result: (Any?) -> ()) -> () in libleak_detector.a(SwiftLeakDetectorPlugin.o)
"static (extension in Foundation):Swift.String.unconditionallyBridgeFromObjectiveC(__C.NSString?) -> Swift.String", referenced from:
leak_detector.SwiftLeakDetectorPlugin.handle(
: __C.FlutterMethodCall, result: (Any?) -> ()) -> () in libleak_detector.a(SwiftLeakDetectorPlugin.o)
"swift_getInitializedObjCClass", referenced from:
type metadata accessor for __C.FlutterMethodChannel in libleak_detector.a(SwiftLeakDetectorPlugin.o)
type metadata accessor for leak_detector.SwiftLeakDetectorPlugin in libleak_detector.a(SwiftLeakDetectorPlugin.o)
leak_detector.SwiftLeakDetectorPlugin.handle(
: __C.FlutterMethodCall, result: (Any?) -> ()) -> () in libleak_detector.a(SwiftLeakDetectorPlugin.o)
"_swift_FORCE_LOAD$_swiftFoundation", referenced from:
_swift_FORCE_LOAD$swiftFoundation$_leak_detector in libleak_detector.a(SwiftLeakDetectorPlugin.o)
(maybe you meant: _swift_FORCE_LOAD$swiftFoundation$_leak_detector)
"_swift_FORCE_LOAD$_swiftCoreAudio", referenced from:
_swift_FORCE_LOAD$swiftCoreAudio$_leak_detector in libleak_detector.a(SwiftLeakDetectorPlugin.o)
(maybe you meant: _swift_FORCE_LOAD$swiftCoreAudio$leak_detector)
"static Swift.String.+ infix(Swift.String, Swift.String) -> Swift.String", referenced from:
leak_detector.SwiftLeakDetectorPlugin.handle(
: __C.FlutterMethodCall, result: (Any?) -> ()) -> () in libleak_detector.a(SwiftLeakDetectorPlugin.o)
"_swift_FORCE_LOAD$_swiftDarwin", referenced from:
_swift_FORCE_LOAD$swiftDarwin$_leak_detector in libleak_detector.a(SwiftLeakDetectorPlugin.o)
(maybe you meant: _swift_FORCE_LOAD$swiftDarwin$_leak_detector)
"_swift_unknownObjectRelease", referenced from:
static leak_detector.SwiftLeakDetectorPlugin.register(with: __C.FlutterPluginRegistrar) -> () in libleak_detector.a(SwiftLeakDetectorPlugin.o)
@nonobjc __C.FlutterMethodChannel.__allocating_init(name: Swift.String, binaryMessenger: __C.FlutterBinaryMessenger) -> __C.FlutterMethodChannel in libleak_detector.a(SwiftLeakDetectorPlugin.o)
@objc static leak_detector.SwiftLeakDetectorPlugin.register(with: __C.FlutterPluginRegistrar) -> () in libleak_detector.a(SwiftLeakDetectorPlugin.o)
reabstraction thunk helper from @escaping @callee_unowned @convention(block) (@unowned Swift.AnyObject?) -> () to @escaping @callee_guaranteed (@in_guaranteed Any?) -> () in libleak_detector.a(SwiftLeakDetectorPlugin.o)
"_swift_FORCE_LOAD$_swiftDispatch", referenced from:
_swift_FORCE_LOAD$swiftDispatch$_leak_detector in libleak_detector.a(SwiftLeakDetectorPlugin.o)
(maybe you meant: _swift_FORCE_LOAD$swiftDispatch$_leak_detector)
"swift_release", referenced from:
leak_detector.SwiftLeakDetectorPlugin.handle(
: __C.FlutterMethodCall, result: (Any?) -> ()) -> () in libleak_detector.a(SwiftLeakDetectorPlugin.o)
__swift_destroy_boxed_opaque_existential_0 in libleak_detector.a(SwiftLeakDetectorPlugin.o)
@objc leak_detector.SwiftLeakDetectorPlugin.handle(
: __C.FlutterMethodCall, result: (Any?) -> ()) -> () in libleak_detector.a(SwiftLeakDetectorPlugin.o)
"_swift_deallocObject", referenced from:
l_objectdestroy in libleak_detector.a(SwiftLeakDetectorPlugin.o)
"_swift_FORCE_LOAD$_swiftMetal", referenced from:
_swift_FORCE_LOAD$swiftMetal$_leak_detector in libleak_detector.a(SwiftLeakDetectorPlugin.o)
(maybe you meant: _swift_FORCE_LOAD$swiftMetal$_leak_detector)
"swift_retain", referenced from:
leak_detector.SwiftLeakDetectorPlugin.handle(
: __C.FlutterMethodCall, result: (Any?) -> ()) -> () in libleak_detector.a(SwiftLeakDetectorPlugin.o)
"_swift_FORCE_LOAD$_swiftObjectiveC", referenced from:
_swift_FORCE_LOAD$swiftObjectiveC$_leak_detector in libleak_detector.a(SwiftLeakDetectorPlugin.o)
(maybe you meant: _swift_FORCE_LOAD$swiftObjectiveC$_leak_detector)
"_swift_unknownObjectRetain", referenced from:
@objc static leak_detector.SwiftLeakDetectorPlugin.register(with: __C.FlutterPluginRegistrar) -> () in libleak_detector.a(SwiftLeakDetectorPlugin.o)
"Swift._bridgeAnythingToObjectiveC(A) -> Swift.AnyObject", referenced from:
reabstraction thunk helper from @escaping @callee_unowned @convention(block) (@unowned Swift.AnyObject?) -> () to @escaping @callee_guaranteed (@in_guaranteed Any?) -> () in libleak_detector.a(SwiftLeakDetectorPlugin.o)
"_swift_getObjCClassMetadata", referenced from:
type metadata accessor for __C.FlutterMethodChannel in libleak_detector.a(SwiftLeakDetectorPlugin.o)
@objc static leak_detector.SwiftLeakDetectorPlugin.register(with: __C.FlutterPluginRegistrar) -> () in libleak_detector.a(SwiftLeakDetectorPlugin.o)
"(extension in Foundation):Swift.String._bridgeToObjectiveC() -> __C.NSString", referenced from:
@nonobjc __C.FlutterMethodChannel.__allocating_init(name: Swift.String, binaryMessenger: __C.FlutterBinaryMessenger) -> __C.FlutterMethodChannel in libleak_detector.a(SwiftLeakDetectorPlugin.o)
"_swift_getObjCClassFromMetadata", referenced from:
@nonobjc __C.FlutterMethodChannel.__allocating_init(name: Swift.String, binaryMessenger: __C.FlutterBinaryMessenger) -> __C.FlutterMethodChannel in libleak_detector.a(SwiftLeakDetectorPlugin.o)
"_swift_FORCE_LOAD$_swiftCoreMedia", referenced from:
_swift_FORCE_LOAD$swiftCoreMedia$_leak_detector in libleak_detector.a(SwiftLeakDetectorPlugin.o)
(maybe you meant: _swift_FORCE_LOAD$swiftCoreMedia$leak_detector)
"type metadata for Swift.String", referenced from:
leak_detector.SwiftLeakDetectorPlugin.handle(
: __C.FlutterMethodCall, result: (Any?) -> ()) -> () in libleak_detector.a(SwiftLeakDetectorPlugin.o)
"swift_bridgeObjectRelease", referenced from:
@nonobjc __C.FlutterMethodChannel.__allocating_init(name: Swift.String, binaryMessenger: __C.FlutterBinaryMessenger) -> __C.FlutterMethodChannel in libleak_detector.a(SwiftLeakDetectorPlugin.o)
leak_detector.SwiftLeakDetectorPlugin.handle(
: __C.FlutterMethodCall, result: (Any?) -> ()) -> () in libleak_detector.a(SwiftLeakDetectorPlugin.o)
"Swift.String.init(builtinStringLiteral: Builtin.RawPointer, utf8CodeUnitCount: Builtin.Word, isASCII: Builtin.Int1) -> Swift.String", referenced from:
static leak_detector.SwiftLeakDetectorPlugin.register(with: __C.FlutterPluginRegistrar) -> () in libleak_detector.a(SwiftLeakDetectorPlugin.o)
leak_detector.SwiftLeakDetectorPlugin.handle(
: __C.FlutterMethodCall, result: (Any?) -> ()) -> () in libleak_detector.a(SwiftLeakDetectorPlugin.o)
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

how to set --no-dds in add-to-app

Add the --disable-dds parameter after flutter run to turn off the DDS. After testing, this will not cause any impact on debugging

My flutter module is add-to-app,so how can i set --no-dds

visitChildElements() called during build

有些页面pop的时候,会出现以下错误
visitChildElements() called during build.
The Build Context.visitChildElements()
method can't be called during build
because the child list is still being updated
at that point, so the children might not be
constructed yet, or might be old children
that are going to be replaced.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.