Repository navigation
Open
Labels
P2Important issues not at the top of the work listImportant issues not at the top of the work listengineflutter/engine related. See also e: labels.flutter/engine related. See also e: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onThe issue has been confirmed reproducible and is ready to work onplatform-androidAndroid applications specificallyAndroid applications specificallyteam-androidOwned by Android platform teamOwned by Android platform teamtriaged-androidTriaged by Android platform teamTriaged by Android platform team
Description
Steps to reproduce
Steps to Reproduce
- Run the attached minimal app on an Android device (tested on ARM64).
- Open Android Studio Profiler or run
adb shell dumpsys meminfo <package>. - Observe Native Heap / Graphics memory while the app is running.
Expected results
Expected behavior
Native memory should stabilize. Calling ui.Paragraph.dispose() should release underlying Skia/HWUI resources in a timely manner.
Actual results
Actual behavior
Native memory grows monotonically and never fully reclaims, even though Dart heap remains stable. After several minutes, Graphics and Unknown categories dominate memory usage.
Code sample
Details
import 'dart:async';
import 'dart:math';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter StringTOASCII',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyHomePage(title: 'StringTOASCII'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool _isAutoGenerating = false;
Timer? _timer;
final Random _random = Random();
/// ✅ 用 ValueNotifier 驱动 CustomPainter
final ValueNotifier<String> _asciiNotifier =
ValueNotifier('等待生成...');
String _generateRandomString(int length) {
const chars =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#\$%^&*()_+-=[]{}|;:,.<>?';
return String.fromCharCodes(
Iterable.generate(
length,
(_) => chars.codeUnitAt(_random.nextInt(chars.length)),
),
);
}
String _convertToAscii(String input) {
return input.runes
.map((code) =>
code.toRadixString(16).padLeft(2, '0').toUpperCase())
.join(' ');
}
void _startAutoGenerate() {
if (_isAutoGenerating) return;
setState(() => _isAutoGenerating = true);
_timer = Timer.periodic(const Duration(milliseconds: 500), (_) {
final randomLength = _random.nextInt(30) + 1;
final randomString = _generateRandomString(randomLength);
final ascii = _convertToAscii(randomString);
/// ✅ 只更新数据,不 rebuild widget 树
_asciiNotifier.value = ascii;
});
}
void _stopAutoGenerate() {
if (!_isAutoGenerating) return;
_timer?.cancel();
setState(() => _isAutoGenerating = false);
}
@override
void dispose() {
_timer?.cancel();
_asciiNotifier.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
/// ✅ 固定高度,避免 relayout
Container(
width: double.infinity,
height: 120,
margin: const EdgeInsets.all(20),
decoration: BoxDecoration(
border: Border.all(color: Colors.grey),
borderRadius: BorderRadius.circular(8),
color: Colors.grey.withOpacity(0.05),
),
child: CustomPaint(
painter: HexPainter(_asciiNotifier),
size: const Size(double.infinity, 120),
),
),
ElevatedButton(
onPressed: _isAutoGenerating ? null : _startAutoGenerate,
child: const Text('开始自动生成'),
),
ElevatedButton(
onPressed: _isAutoGenerating ? _stopAutoGenerate : null,
child: const Text('停止自动生成'),
),
],
),
),
);
}
}
/// ✅ 用 Listenable 驱动,保证每次 value 变化都会 repaint
class HexPainter extends CustomPainter {
final ValueNotifier<String> notifier;
ui.Paragraph? _paragraph;
HexPainter(this.notifier) : super(repaint: notifier);
void _updateParagraph(String text, double maxWidth) {
final builder = ui.ParagraphBuilder(
ui.ParagraphStyle(
textAlign: TextAlign.left,
fontSize: 16,
fontFamily: 'monospace',
fontWeight: ui.FontWeight.bold,
),
)
..pushStyle(ui.TextStyle(color: Colors.black))
..addText('HEX编码:\n$text');
_paragraph?.dispose(); // ✅ 先释放旧的
_paragraph = builder.build()
..layout(ui.ParagraphConstraints(width: maxWidth));
}
@override
void paint(Canvas canvas, Size size) {
final text = notifier.value;
_updateParagraph(text, size.width - 32);
canvas.drawParagraph(
_paragraph!,
const Offset(16, 0),
);
}
@override
bool shouldRepaint(covariant HexPainter oldDelegate) => false;
}
This is a minimal reproducible example. No WebView, no PlatformView, no images.
Screenshots or Video
Screenshots / Video demonstration
[Upload media here]
Logs
Logs
[Paste your logs here]Flutter Doctor output
Details
Flutter assets will be downloaded from https://storage.flutter-io.cn. Make sure you trust this source!
Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel stable, 3.32.0, on Microsoft Windows [版本 10.0.26200.8875], locale zh-CN)
[√] Windows Version (Windows 11 or higher, 25H2, 2009)
[!] Android toolchain - develop for Android devices (Android SDK version 36.1.0)
! Some Android licenses not accepted. To resolve this, run: flutter doctor --android-licenses
[√] Chrome - develop for the web
[X] Visual Studio - develop Windows apps
X Visual Studio not installed; this is necessary to develop Windows apps.
Download at https://visualstudio.microsoft.com/downloads/.
Please install the "Desktop development with C++" workload, including all of its default components
[√] Android Studio (version 2024.3)
[√] VS Code (version unknown)
X Unable to determine VS Code version.
[√] Connected device (4 available)Metadata
Metadata
Assignees
Labels
P2Important issues not at the top of the work listImportant issues not at the top of the work listengineflutter/engine related. See also e: labels.flutter/engine related. See also e: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onThe issue has been confirmed reproducible and is ready to work onplatform-androidAndroid applications specificallyAndroid applications specificallyteam-androidOwned by Android platform teamOwned by Android platform teamtriaged-androidTriaged by Android platform teamTriaged by Android platform team
Activity
fangxinbaize commentedon Jul 21, 2026
Note: the
!(Android licenses) and[X] Visual Studioin doctor are unrelated to this issue (Windows host only, target is Android arm64). Licenses have since been accepted; behavior unchanged on a cleanflutter doctorrun.This minimal repro was extracted from a real app:
evaluateJavascriptdumpsys meminfo) grows monotonically, Graphics/Unknown dominateThe sample above removes WebView/PlatformView entirely to isolate:
high-frequency CustomPainter.repaint → ui.Paragraph → native Skia/HWUI allocation
which appears to be one contributor to the real app's leak.
saurabh-mirajkar commentedon Jul 21, 2026
Thanks for the detailed report. I tested it on a physical Pixel 6 (Android 17) but wasn't able to reproduce the reported behavior.
Over several minutes of running (~30 mins), I observed only a small increase in Native Heap before it appeared to stabilize, while the Graphics memory remained essentially unchanged. I also noticed the report was filed using Flutter
3.32.0, whereas the current stable release is3.44.7.Could you confirm whether this is still reproducible on Flutter
3.44.7? If so, could you also share a memory profile (Android Studio Profiler oradb shell dumpsys meminfo) showing the continuous growth over time?sky125801 commentedon Jul 21, 2026
@saurabh-mirajkar @fangxinbaize
I also encountered the issue of native heap continuously growing:
Flutter 3.44, Android 16, Galaxy S25 Ultra.
In addition, I ran the same Flutter app on Windows and observed the same native heap growth phenomenon.
The following is a demo that can quickly reproduce the issue.
main_bloc.dart
main_event.dart
main_state.dart
main.dart
This phenomenon of native heap continuously growing will persist until memory is exhausted.
fangxinbaize commentedon Jul 22, 2026
@saurabh-mirajkar
Thank you for testing this issue on the Pixel 6!
I have upgraded my environment to the version you mentioned (3.44, currently the latest stable) and retested on my device (Android 14).
I can confirm that the issue is still reproducible on this version. Notably, I observed a clear correlation between the update frequency and the rate of memory growth: the faster the CustomPainter repaint interval, the quicker the Native Heap climbs.
In addition, a 30‑minute test duration may be a bit too short; I would suggest running longer continuous tests to more clearly observe the long‑term trend of memory growth.
saurabh-mirajkar commentedon Jul 22, 2026
@fangxinbaize Thanks for checking on the latest stable.
I also tested the attached sample on Flutter
3.44.7using a Pixel 6 and monitoredadb shell dumpsys meminfoover approximately two hours. In my testing, the native heap increased during the initial warm-up period (~29.5 MB → ~33.6 MB), then stabilized around 32–33 MB rather than continuing to grow.Since we're seeing different behavior, could you share a longer series of
adb shell dumpsys meminfosnapshots (or Android Studio Native Memory profiler captures) from your device on3.44.x? That would help determine whether the native heap continues to grow over time or eventually reaches a steady state.I've attached my meminfo.log for reference.
fangxinbaize commentedon Jul 23, 2026
@saurabh-mirajkar
Thank you for your continued testing. Our observations are indeed different. From yesterday afternoon to now, my app has been running continuously overnight, and the native heap has grown from over 40 MB to over 200 MB, with no sign of decreasing.
Did you click the start button during your test? There is a button labeled "开始自动生成" on the app, and the HEX display panel keeps updating. If possible, could you change the generation interval from 500 ms to 100 ms, or even faster, say 50 ms? In the code, this method:
Attached is the memory info from my Android device this [morning.]
meninfo.txt
Thanks again for your support.
saurabh-mirajkar commentedon Jul 23, 2026
@fangxinbaize Thanks for the additional details.
I retested this on the latest stable (Flutter 3.44.7) using the provided sample on a physical Pixel 6. I tapped on 开始自动生成 button and collected
adb shell dumpsys meminfosnapshots approximately every 10 minutes over a ~4-hour run.I also observed gradual native heap growth during the test, although the growth rate on my device was lower than the one reported in the original issue. Attaching my meminfo log in case it's helpful for comparison. Routing this for further investigation.
fangxinbaize commentedon Jul 27, 2026
@saurabh-mirajkar
Thank you for retesting and for sharing the detailed data! Your results perfectly corroborate the issue we're seeing—the Native Heap continues to grow gradually even on the stable channel.
Our team is currently conducting long-term stability tests for our app, and this memory growth is preventing it from running reliably over extended periods. Could you please let us know if there are any updates on the investigation? We look forward to your reply.
fangxinbaize commentedon Aug 17, 2026
@jesswrd @saurabh-mirajkar
linux_meminfo.txt
I’ve reproduced this issue on both Ubuntu 22.04 and Windows, not only on Android. This indicates that the memory leak is not platform‑specific but rather a general defect in the engine layer.
Moreover, the problem only becomes clearly visible after prolonged stress testing (e.g., >48 hours). Short runs (e.g., 2 hours) may show a seemingly stable memory footprint, but over extended periods the native heap keeps growing linearly, which confirms a true leak rather than temporary fluctuations.
Attached is my test log from Ubuntu 22.04, with memory samples taken every 5 minutes. The data clearly illustrates the cumulative upward trend over time, which I hope will be useful for the team’s investigation.