-
Notifications
You must be signed in to change notification settings - Fork 5
Closed
Labels
enhancementNew feature or requestNew feature or request
Description
前置确认
- 我理解 Issue 是用于反馈和解决问题的,而非吐槽评论区,将尽可能提供更多信息
- 我未仔细阅读这些内容,只是一键已读所有内容,并相信这不会影响问题的处理
- 我已搜索现有 Issue,确认这不是重复的功能请求
- 我已查看 README 中的 Roadmap
- 这个功能将使多个用户受益,而不仅仅是我自己
功能类型
Java 管理
问题陈述
当前的 Java 检测逻辑(src-tauri/src/core/java.rs 中的 get_java_candidates() 函数)存在以下问题:
现存问题
-
代码冗长且难以维护
- 652-812 行(160+ 行)包含大量硬编码路径和平台特定逻辑
- 每个平台都有独立的路径扫描代码块
- 维护成本高,添加新路径需要修改多处
-
检测范围过大
- 遍历系统中所有可能的 Java 安装路径:
- Linux:
/usr/lib/jvm,/usr/java,/opt/java,/opt/jdk,/opt/openjdk, SDKMAN 路径等 - macOS:
/Library/Java/JavaVirtualMachines, Homebrew 路径等 - Windows:
C:\Program Files\Java, Eclipse Adoptium, AdoptOpenJDK, Microsoft JDK, Zulu, Corretto, LibericaJDK 等
- Linux:
- 遍历系统中所有可能的 Java 安装路径:
-
性能问题
- 即使找到合适的 Java 也会继续扫描所有路径
- 大量文件系统 I/O 操作拖慢启动速度
-
与 DropOut 的 Java 下载机制理念冲突
- 我们已经提供了完整的 Java 自动下载功能
- 为何还要如此复杂地检测系统 Java?
- 这会导致用户困惑:"为什么我下载了 Java 还检测不到?"
当前架构问题
// 当前逻辑(652-812 行)
fn get_java_candidates() -> Vec<PathBuf> {
let mut candidates = Vec::new();
// 检查 PATH
if let Ok(output) = Command::new("where/which").arg("java").output() { ... }
#[cfg(target_os = "linux")]
{
// Linux: 50+ 行硬编码路径
for base in ["/usr/lib/jvm", "/usr/java", "/opt/java", ...] { ... }
}
#[cfg(target_os = "macos")]
{
// macOS: 40+ 行硬编码路径
for path in ["/Library/Java/...", "/opt/homebrew/...", ...] { ... }
}
#[cfg(target_os = "windows")]
{
// Windows: 60+ 行硬编码路径
for base in ["C:\\Program Files\\Java", ...] { ... }
}
// 检查 JAVA_HOME(重复检查)
if let Ok(java_home) = std::env::var("JAVA_HOME") { ... }
candidates
}考虑到 DropOut 已经提供了:
- 内置 Adoptium Java 下载功能
- 版本管理和缓存机制
- 可靠的 Java 版本兼容性保证
- 按需下载,节省磁盘空间
过度依赖系统 Java 检测反而带来了不必要的复杂性和潜在 bug。
建议的解决方案
采用 最小化系统 Java 检测策略,优先使用 DropOut 管理的 Java。
新的检测优先级顺序
1. DropOut 下载的 Java(app_data_dir/java/*) ← 优先级最高,完全可控
↓ 如果没有找到合适版本
2. JAVA_HOME 环境变量 ← 用户显式配置,应当尊重
↓ 如果仍未找到
3. 提示用户通过 DropOut 下载 Java ← 引导用户使用内置功能
代码简化方案
重构后的核心函数:
/// 检测所有可用的 Java 安装(优先 DropOut 管理的 Java)
pub fn detect_all_java_installations(app_handle: &AppHandle) -> Vec<JavaInstallation> {
let mut installations = Vec::new();
// 第一层:DropOut 下载的 Java(优先级最高)
installations.extend(detect_dropout_java(app_handle));
// 第二层:JAVA_HOME 环境变量(用户显式配置)
if let Ok(java_home) = std::env::var("JAVA_HOME") {
let java_bin = find_java_executable(&PathBuf::from(&java_home));
if let Some(path) = java_bin {
if let Some(java) = check_java_installation(&path) {
if !installations.iter().any(|j| j.path == java.path) {
installations.push(java);
}
}
}
}
// 去重并排序(DropOut Java 优先,然后按版本降序)
installations.sort_by(|a, b| {
let is_dropout_a = a.path.contains("dropout") || a.path.contains("temurin");
let is_dropout_b = b.path.contains("dropout") || b.path.contains("temurin");
match (is_dropout_a, is_dropout_b) {
(true, false) => std::cmp::Ordering::Less, // DropOut Java 优先
(false, true) => std::cmp::Ordering::Greater,
_ => parse_java_version(&b.version).cmp(&parse_java_version(&a.version)),
}
});
installations
}
/// 检测 DropOut 下载的 Java 版本
fn detect_dropout_java(app_handle: &AppHandle) -> Vec<JavaInstallation> {
let mut installations = Vec::new();
let dropout_java_dir = get_java_install_dir(app_handle);
if !dropout_java_dir.exists() {
return installations;
}
if let Ok(entries) = std::fs::read_dir(&dropout_java_dir) {
for entry in entries.flatten() {
let path = entry.path();
if path.is_dir() {
if let Some(java_bin) = find_java_executable(&path) {
if let Some(java) = check_java_installation(&java_bin) {
installations.push(java);
}
}
}
}
}
installations
}移除的代码
get_java_candidates()的 160 行平台特定路径扫描(652-812 行)detect_java_installations()的复杂逻辑(626-650 行)- 所有硬编码的系统路径:
- Linux:
/usr/lib/jvm,/usr/java,/opt/java, SDKMAN 等 - macOS:
/Library/Java, Homebrew, Cellar 等 - Windows:
Program Files\Java, Eclipse Adoptium, AdoptOpenJDK 等
- Linux:
保留的功能
JAVA_HOME环境变量检测(用户显式配置)- DropOut 下载的 Java 管理
- Java 版本兼容性检查(
get_compatible_java,is_java_compatible) - Java 自动下载功能(
download_and_install_java)
替代方案
如果必须保留系统 Java 检测,使用现成的 crate 而不是自己维护 160 行代码:
[dependencies]
java-locator = "0.1.9"// 使用 java-locator
if let Ok(java_home) = java_locator::locate_java_home() {
// 使用检测到的 Java
}示例和参考
其他启动器的做法
-
Prism Launcher 9.0+
- 提供"Auto-download Mojang Java"选项
- 优先使用启动器下载的 Java
- 系统 Java 检测是可选功能
-
ATLauncher
- 默认使用内置 Java
- 仅在高级设置中允许指定系统 Java
- 不主动扫描系统路径
-
GDLauncher
- 完全使用自己管理的 Java
- 不检测系统安装
- 提供清晰的 Java 版本选择界面
优先级
中(锦上添花)
贡献意愿
- 我愿意实现这个功能
- 我愿意帮助测试这个功能
- 我可以提供设计草图或规范
其他信息
No response
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request