Flutter问题记录 - Unable to find bundled Java version(续)

本文分析了Flutter项目在Android端构建失败的原因,详细解释了javaPath配置不当导致的问题,并提供了修复方案。


前言

Flutter问题记录 - Unable to find bundled Java version文章中主要对Unable to find bundled Java version报错进行了分析,虽然从最终结果上看,Android端构建运行失败和出现这个报错的原因应该是一致的,但是没有进行原因分析。这里做一些简单分析作为上篇文章的补充。

开发环境

  • Android Studio: 2022.1.1
  • Flutter: 3.3.10

问题描述

Android端构建运行失败,报错信息如下:

Execution failed for task ':app:processDebugMainManifest'.
> Unable to make field private final java.lang.String java.io.File.path accessible: module java.base does not "opens java.io" to unnamed module

2023/08/14更新:当前问题已被修复,如果你还遇到以上报错,可以参考这篇文章Android问题记录 - Unable to make field private final java.lang.String java.io.File.path accessible(持续更新)

问题分析

当我们在Android Studio中点击运行Flutter项目到Android设备时,控制台会输出:

Launching xxx.dart on xxx in debug mode...
Running Gradle task 'assembleDebug'...
...

当然,如果项目没执行过pub get,还会有这个输出:

Running "flutter pub get" in xxx...

对于Launching xxx.dart on xxx in debug mode...输出和要分析的问题没有什么关系,不过,如果你对整个运行流程感兴趣的话,可以在Flutter框架项目下的packages/flutter_tools/lib/src/resident_runner.dart文件中找到这个输出的相关代码:

final String modeName = coldRunner.debuggingOptions.buildInfo.friendlyModeName;
final bool prebuiltMode = coldRunner.applicationBinary != null;
globals.printStatus(
  'Launching ${getDisplayPath(coldRunner.mainPath, globals.fs)} '
  'on ${device!.name} in $modeName mode...',
);

对于Running Gradle task 'assembleDebug'...输出就是这次问题分析的关键了,在Flutter框架项目下搜索关键词Running Gradle task

screenshot1

上篇文章的问题分析可以知道,问题出在Android Studio移除了jre目录,进而导致javaPath的拼接出现了问题。那现在这问题会不会是因为运行Gradle task时也用到了错误的javaPath呢?继续在gradle.dart文件中搜索javaPath

gradle.dart文件中buildGradleApp方法的部分代码:

try {
  exitCode = await _processUtils.stream(
    command,
    workingDirectory: project.android.hostAppGradleRoot.path,
    allowReentrantFlutter: true,
    environment: <String, String>{
      if (javaPath != null)
        'JAVA_HOME': javaPath!,
    },
    mapFunction: consumeLog,
  );
} on ProcessException catch (exception) {
  consumeLog(exception.toString());
  // Rethrow the exception if the error isn't handled by any of the
  // `localGradleErrors`.
  if (detectedGradleError == null) {
    rethrow;
  }
} finally {
  status.stop();
}

可以看到,确实用到了javaPath,那这个和android_studio.dart文件里面的javaPath有什么关联吗?选中javaPath跳转定义的地方,发现来到了android_studio.dart文件,是一个顶级方法:

String? get javaPath => globals.androidStudio?.javaPath;

Dart的顶级方法意味着只要导入android_studio.dart文件,就可以直接调用javaPath方法。从方法定义中的javaPath继续跳转,来到了AndroidStudio类里面。

AndroidStudio类部分代码:

class AndroidStudio implements Comparable<AndroidStudio> {
  AndroidStudio(
    this.directory, {
    Version? version,
    this.configured,
    this.studioAppName = 'AndroidStudio',
    this.presetPluginsPath,
  }) : version = version ?? Version.unknown {
    _init(version: version);
  }
  
  String? _javaPath;
  bool _isValid = false;
  final List<String> _validationMessages = <String>[];

  String? get javaPath => _javaPath;

  void _init({Version? version}) {
    _isValid = false;
    _validationMessages.clear();

    if (configured != null) {
      _validationMessages.add('android-studio-dir = $configured');
    }

    if (!globals.fs.isDirectorySync(directory)) {
      _validationMessages.add('Android Studio not found at $directory');
      return;
    }

    final String javaPath = globals.platform.isMacOS ?
        version != null && version.major < 2020 ?
        globals.fs.path.join(directory, 'jre', 'jdk', 'Contents', 'Home') :
        globals.fs.path.join(directory, 'jre', 'Contents', 'Home') :
        globals.fs.path.join(directory, 'jre');
    final String javaExecutable = globals.fs.path.join(javaPath, 'bin', 'java');
    if (!globals.processManager.canRun(javaExecutable)) {
      _validationMessages.add('Unable to find bundled Java version.');
    } else {
      RunResult? result;
      try {
        result = globals.processUtils.runSync(<String>[javaExecutable, '-version']);
      } on ProcessException catch (e) {
        _validationMessages.add('Failed to run Java: $e');
      }
      if (result != null && result.exitCode == 0) {
        final List<String> versionLines = result.stderr.split('\n');
        final String javaVersion = versionLines.length >= 2 ? versionLines[1] : versionLines[0];
        _validationMessages.add('Java version $javaVersion');
        _javaPath = javaPath;
        _isValid = true;
      } else {
        _validationMessages.add('Unable to determine bundled Java version.');
      }
    }
  }
}

继续在类里面搜索_javaPath,来到了AndroidStudio类的初始化方法_init

screenshot2

可以发现Android端构建运行和flutter doctor命令执行一样,也用到了AndroidStudio类里面拼接的javaPath。当Android Studio移除jre目录后,初始化androidStudio对象时拼接的javaPath路径有问题导致没有给_javaPath赋值,从而导致Android端构建运行时获取的javaPathnull。由此可以验证Android端构建运行失败的原因和出现Unable to find bundled Java version报错的原因是一致的。

解决方案

请看这篇文章Flutter问题记录 - Unable to find bundled Java version中的解决方案。

最后

如果这篇文章对你有所帮助,点赞👍加星🌟支持一下吧,谢谢~


本篇文章由@crasowas发布于优快云。

<think>好的,用户遇到了“Unable to find bundled Java version”的问题,需要解决方案。我需要先理解这个错误出现的背景。根据引用内容,这个问题通常出现在安装Flutter后运行flutter doctor时,尤其是在Android Studio中找不到捆绑的Java版本。 首先,用户可能已经安装了Android Studio,但缺少了jre或jdk目录。根据引用[2],解决方案是检查Android Studio.app/Contents目录下是否有jre文件夹。如果没有,需要创建并将jbr的内容复制进去。同时,还要确保jre目录下有jdk文件夹,如果没有,同样需要创建并复制文件。这可能是因为Android Studio版本更新后目录结构变化导致的。 接下来,我需要验证这些步骤是否有效。引用[3]提到用户的Flutter版本是3.7.3,可能他们使用的Android Studio版本较新,比如2022.1,这可能改变了默认的Java路径。因此,手动创建jre目录并复制文件可以解决路径问题。 另外,用户可能需要检查环境变量是否正确设置,或者是否需要重新配置Java路径。不过根据提供的引用,主要问题还是目录结构的问题。需要确保用户按照步骤操作,特别是复制正确的文件到指定位置。 可能用户在执行这些步骤后,需要重新运行flutter doctor来验证是否解决。如果问题依旧,可能需要检查权限问题,或者是否有其他配置错误。但根据现有引用,目录结构的调整应该是主要解决方案。</think>### 解决方案:Unable to find bundled Java version #### 问题原因 此错误通常由Android Studio安装目录缺少`jre`或`jdk`子目录引起,导致Flutter无法检测到Android Studio捆绑的Java环境[^2][^3]。 --- #### 逐步解决方法 1. **定位Android Studio安装目录** - macOS默认路径:`/Applications/Android Studio.app/Contents` - Windows默认路径:`C:\Program Files\Android\Android Studio` 2. **检查并修复`jre`目录** - 进入`Contents`目录,若**无`jre`文件夹**,则手动创建。 - 将`Contents/jbr`文件夹内的**全部内容**复制到新建的`jre`目录中。 ```bash # macOS示例命令 cp -R /Applications/Android\ Studio.app/Contents/jbr/* /Applications/Android\ Studio.app/Contents/jre/ ``` 3. **检查并修复`jdk`目录(部分版本需要)** - 进入`Contents/jre`目录,若**无`jdk`文件夹**,则手动创建。 - 将`jre`目录中的文件复制到`jdk`文件夹内。 4. **验证修复结果** - 重新运行`flutter doctor`,观察错误是否消失。 - 若仍报错,尝试重启终端或IDE。 --- #### 补充说明 -问题常见于Android Studio 2022.1及以上版本[^3]。 - 若手动操作无效,可尝试重新安装Android Studio并选择**包含Java环境**的选项。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值