调试Flutter应用时,Dart虚拟机如何工作?

3

我是一名原生iOS开发者,最近正在学习Flutter。从Flutter的一些教程中了解到,Dart支持AOT和JIT两种编译方式。在发布时,应用程序会通过AOT将Dart代码编译为机器码;在调试时,Dart代码将通过带有Dart虚拟机的JIT执行,这将使热重载成为可能。

我的问题是,在调试时Dart虚拟机是如何工作的?以iOS应用程序为例,由于iOS应用程序运行在其自己的沙盒中,Dart虚拟机在哪里运行?虚拟机是否在应用程序进程中运行?也许它像后台运行的子线程一样,在应用程序运行时实时将Dart代码解释为机器码?

1个回答

1

Dart VM是用C++编写的,Flutter中只有一个相对较小的部分是用iOS编写的,称为shell。对于iOS,您可以在Flutter/engine的此目录中找到文件。我自己还在学习/浏览Flutter内部。

回答您的问题,Dart VM在所有隔离区之间共享,并在您的应用程序进程中运行。在一个进程中只能运行1个Dart VM,这是Dart VM的设计(而不是构造它,您要求一个,它会给您相同的一个,也就是单例模式)。一个普通的flutter应用程序是一个单独的隔离区,但您可以在一个iOS进程/应用程序中运行多个Flutter Engines/ Dart入口点(main方法)。Dart VM管理隔离区,因此它不在一个线程中运行。从阅读mrale.ph/dartvm,内部使用线程池和管理操作系统线程,因此绝对不限于一个线程。

操作系统线程和隔离区之间的关系有些模糊,并且高度依赖于VM嵌入到应用程序中的方式。

VM内部使用线程池(dart::ThreadPool)管理操作系统线程,并且代码的结构是围绕着dart::ThreadPool::Task的概念而非操作系统线程的概念进行构建的。

更多调查

阅读https://mrale.ph/dartvm/,您可以克隆Flutter/engine project并查找FLUTTER_RUNTIME_MODE字符串,以了解在调试、分析、发布和JIT发布之间的Flutter逻辑变化。

例如,在Dart VM中(dart_vm.cc):

#if (FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG)
#if !OS_IOS && !OS_MACOSX
  // Debug mode uses the JIT, disable code page write protection to avoid
  // memory page protection changes before and after every compilation.
  PushBackAll(&args, kDartWriteProtectCodeArgs,
              fml::size(kDartWriteProtectCodeArgs));
#else
  const bool tracing_result = EnableTracingIfNecessary(settings_);
  // This check should only trip if the embedding made no attempts to enable
  // tracing. At this point, it is too late display user visible messages. Just
  // log and die.
  FML_CHECK(tracing_result)
      << "Tracing not enabled before attempting to run JIT mode VM.";
#if TARGET_CPU_ARM
  // Tell Dart in JIT mode to not use integer division on armv7
  // Ideally, this would be detected at runtime by Dart.
  // TODO(dnfield): Remove this code
  // https://github.com/dart-lang/sdk/issues/24743
  PushBackAll(&args, kDartDisableIntegerDivisionArgs,
              fml::size(kDartDisableIntegerDivisionArgs));
#endif  // TARGET_CPU_ARM
#endif  // !OS_IOS && !OS_MACOSX
#endif  // (FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG)

或者,在 FlutterPluginAppLifeCycleDelegate.mm 中:

您可以看到,如果应用程序在调试模式下运行,则当应用程序进入前台时,后台任务 _debugBackgroundTask 将被取消。当设备屏幕锁定时,这个 _debugBackgroundTask 是在应用程序进入后台时创建的,以保持 Flutter 会话的活动状态。更多信息 在此处

- (void)handleWillEnterForeground:(NSNotification*)notification {
  UIApplication* application = [UIApplication sharedApplication];
#if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
  if (_debugBackgroundTask != UIBackgroundTaskInvalid) {
    [application endBackgroundTask:_debugBackgroundTask];
    _debugBackgroundTask = UIBackgroundTaskInvalid;
  }
#endif  // FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG
  for (NSObject<FlutterApplicationLifeCycleDelegate>* delegate in _delegates) {
    if (!delegate) {
      continue;
    }
    if ([delegate respondsToSelector:@selector(applicationWillEnterForeground:)]) {
      [delegate applicationWillEnterForeground:application];
    }
  }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接