# java-manager Bug & Issue Report
> 通过 `cjm` CLI 工具实测 `java-manager` v0.4.0-2b 发现的问题汇总。
---
## 1. `matches_version("1.x")` 不匹配 Java 8
**严重度**: 中
**位置**: `info.rs:296-333` — `JavaInfo::matches_version()`
**描述**: `matches_version` 不会对 version requirement 做 `"1."` 前缀剥离,导致要求 `"1.8"` 时不匹配 Java 8。
```
JavaVersion::parse("1.8.0_482")
→ JavaVersion { major: 8, minor: 0, patch: 482, raw: "1.8.0_482" }
// "1." prefix stripped
matches_version("1.8")
→ req_parts = ["1", "8"]
→ parsed.major == 1 && parsed.minor == 8
→ 8 == 1 ? false ✗
```
而 `matches_version("8")` 正常工作:
```
matches_version("8")
→ req_parts = ["8"]
→ parsed.major == 8
→ true ✓
```
**影响**: 用户习惯用 `"1.8"` 指代 Java 8,但 `best_match()`、`filter_by_version()`、`matches_version()` 均无法处理该格式。
**修复建议**: `matches_version` 对 requirement 做与 `JavaVersion::parse` 相同的 `"1."` 前缀剥离:
```rust
} else {
req
};
```
**复现**:
```
$ cjm use 1.8
error: No Java installation matched version: 1.8
$ cjm use 8
✓ JAVA_HOME set to: \\?\D:\Program Files\Eclipse Adoptium\jdk-8.0.482.8-hotspot
```
---
## 2. `\\?\` 扩展路径前缀泄漏
**严重度**: 中
**位置**: `info.rs:163` — `fs::canonicalize()`
**描述**: `fs::canonicalize()` 在 Windows 上为路径添加 `\\?\` 扩展长度前缀。该前缀泄漏到所有用户可见输出中,并且通过 `setx` 写入注册表环境变量。
```
JAVA_HOME: \\?\D:\Program Files\Eclipse Adoptium\jdk-17.0.19.10-hotspot
```
**影响**:
- 用户界面显示不美观
- `setx` 将 `\\?\` 前缀写入 `JAVA_HOME` 注册表值,部分工具可能不识别此格式路径
- JSON 输出同样包含此前缀
**修复建议**: 使用 `dunce` crate 的 `canonicalize()` 自动去除 `\\?\` 前缀,或 `canonicalize` 后 strip 前缀:
```rust
use std::path::Path;
fn clean_path(p: &Path) -> std::path::PathBuf {
let s = p.to_string_lossy().to_string();
if cfg!(windows) && s.starts_with("\\\\?\\") {
Path::new(&s[4..]).to_path_buf()
} else {
p.to_path_buf()
}
}
```
---
## 3. 架构(Architecture)字段格式不一致
**严重度**: 低
**位置**: `info.rs:211`(来自 release 文件 `OS_ARCH`), `info.rs:546-552`(来自 `java -version`)
**描述**: 架构字段有三种不同格式,取决于数据来源:
| release 文件 `OS_ARCH` | `x86_64` | JDK 17+ (Eclipse Adoptium) |
| release 文件 `OS_ARCH` | `amd64` | JDK 8 (Eclipse Adoptium) |
| `java -version` 解析 | `64-Bit` / `32-Bit` | 无 release 文件时 fallback |
**影响**: 无法通过简单的字符串比较判断架构是否匹配。例如 `"x86_64" != "amd64"` 但实际是同一架构。
**修复建议**: 标准化为统一格式,如:
```rust
fn normalize_arch(arch: &str) -> &str {
match arch {
"x86_64" | "amd64" | "64-Bit" => "x86_64",
"aarch64" | "arm64" => "aarch64",
"32-Bit" | "x86" | "i386" => "x86",
_ => arch,
}
}
```
---
## 4. Vendor 提取逻辑脆弱
**严重度**: 中
**位置**: `info.rs:530-543` — `read_version()` 中的 vendor 解析
**描述**: 从 `java -version` stderr 提取 vendor 的逻辑是:
1. 找包含 `"Runtime Environment"` 的行
2. 取该关键词后的第一个空白分隔词
3. 按 `-` 或 `(` 切分取第一部分
对于标准 OpenJDK 输出:
```
OpenJDK Runtime Environment (build 21.0.11+10-LTS)
```
解析过程:
1. 找到 `"Runtime Environment"`
2. 剩余部分:` (build 21.0.11+10-LTS)`
3. `split_whitespace().next()` → `"(build"`
4. `split(['-', '(']).next()` → `""`(空字符串)
5. 跳过(空字符串不设置 vendor)
6. fallback 到首行判断 → `"OpenJDK"`
**影响**: 对无 `release` 文件的 JDK/JRE 安装(如 Minecraft 捆绑运行时),vendor 将 fallback 为不精确的值。多数标准 JDK 都有 `release` 文件所以此问题被掩盖。
**修复建议**: 使用正则表达式直接匹配 vendor 模式:
```rust
use regex::Regex;
fn extract_vendor_from_stderr(stderr: &str) -> Option<String> {
// "OpenJDK Runtime Environment (Temurin-1.8.0_482-b08)"
// "OpenJDK Runtime Environment (build 11.0.2+9)"
let re = Regex::new(r"Runtime Environment\s+\(([^)-]+)").ok()?;
if let Some(caps) = re.captures(stderr) {
let vendor = caps.get(1)?.as_str().trim();
if !vendor.is_empty() && vendor != "build" {
return Some(vendor.to_string());
}
}
None
}
```
---
## 5. `JavaRunner` 缺少任意命令行模式
**严重度**: 低
**位置**: `execute.rs:444-453`
**描述**: `JavaRunner.execute()` 强制要求 `-jar` 或 main class,无法执行纯粹的 Java 工具命令如 `java -version`、`java --list-modules`、`java -XshowSettings` 等。
`JavaInfo::execute(args)` 可以做到,但不在 `JavaRunner` 的 builder 模式中。
**修复建议**: `JavaRunner` 增加 `.tool(args)` 方法或允许无 jar/main_class 时仅传 JVM 参数:
```rust
pub fn tool(mut self, args: &[&str]) -> Self {
self.tool_args = Some(args.iter().map(|s| s.to_string()).collect());
self
}
```
执行时若 `tool_args` 有值则绕过 jar/main_class 要求。
---
## 总结
| 1 | `matches_version("1.x")` 不匹配 Java 8 | 中 | 0.4.0-2b | API 消费者 |
| 2 | `\\?\` 路径前缀泄漏 | 中 | 0.1.0 | Windows 用户 |
| 3 | 架构字段格式不一致 | 低 | 0.1.0 | API 消费者 |
| 4 | Vendor 提取逻辑脆弱 | 中 | 0.1.0 | 无 release 文件的安装 |
| 5 | JavaRunner 缺少任意命令模式 | 低 | 0.1.0 | CLI 开发者 |
**已在 0.4.0-2b 中修复的问题**:
- `deep_search()` 不再因 Everything 未运行而崩溃(0.4.0-2b 引入 `cfg(feature = "everything")` 条件编译 + fallback)