在Flutter问题记录 - Unable to find bundled Java version文章中主要对Unable to find bundled Java version
报错进行了分析,虽然从最终结果上看,Android端构建运行失败和出现这个报错的原因应该是一致的,但是没有进行原因分析。这里做一些简单分析作为上篇文章的补充。
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
当我们在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
:
从上篇文章的问题分析可以知道,问题出在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
:
可以发现Android端构建运行和flutter doctor
命令执行一样,也用到了AndroidStudio
类里面拼接的javaPath
。当Android Studio移除jre
目录后,初始化androidStudio
对象时拼接的javaPath
路径有问题导致没有给_javaPath
赋值,从而导致Android端构建运行时获取的javaPath
是null
。由此可以验证Android端构建运行失败的原因和出现Unable to find bundled Java version
报错的原因是一致的。
请看这篇文章Flutter问题记录 - Unable to find bundled Java version中的解决方案。
如果这篇文章对你有所帮助,请不要吝啬你的点赞加星,谢谢~