HMCL-dev/HMCL · error · IOException
Missing java executable file
Error message
Missing java executable file
What it means
After parsing the release file, JavaInfo.fromArchive verifies the JDK directory contains a bin/ subdirectory with the platform's java executable (java, javaw.exe, etc.). It throws IOException("Missing java executable file") when either bin/ is absent or the expected executable entry is missing, since the archive does not contain a runnable Java runtime.
Solutions
- Verify the archive matches the target platform so the expected executable name (java vs javaw.exe) exists in bin/.
- Use a full JDK/JRE distribution instead of a stripped or jlink-minimized image lacking bin/java.
- For macOS, ensure the archive is laid out so bin/ and release are at the JDK root HMCL expects.
- Re-download the archive; a truncated download may have dropped bin entries.
Defensive patterns
Strategy: validation
Validate before calling
ArchiveFileTree.Dir<?> binDir = tree.getRoot().getSubDirs().get("bin");
String exe = expectedPlatform.getOperatingSystem().getJavaExecutable();
if (binDir == null || binDir.getFiles().get(exe) == null) {
throw new IOException("Archive JDK has no bin/" + exe);
} Try / catch
try {
JavaInfo info = JavaInfo.fromArchive(tree);
} catch (IOException e) {
if (e.getMessage().contains("Missing java executable")) {
// verify archive platform matches target OS
}
} Prevention
- Match the JDK archive platform to the target OS before parsing
- Use complete JDK/JRE images that ship bin/java (or javaw.exe on Windows)
- Verify downloads are not truncated (compare size/hash)
When it happens
Trigger: JavaInfo.fromArchive(tree) with an archive whose single root dir lacks a 'bin' subdirectory, or whose bin/ does not contain the executable named by info.getPlatform().getOperatingSystem().getJavaExecutable() (e.g. using a linux archive on Windows lookup, or a stripped image).
Common situations: Downloading a JDK for the wrong platform (no javaw.exe on Windows archives is fine, but a mismatched archive lookup fails); jlink custom runtimes missing bin/java; archives with executables under a different layout (e.g. Contents/Home on macOS).
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- Missing release file
- name existing
- Texture url is empty
- Failed to download texture
- Platform is mismatch: expected
AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10).
Data as JSON: /api/errors/96f0695d5b9f43f9.
Report an issue: GitHub.
Appendix: source
Thrown at HMCLCore/src/main/java/org/jackhuang/hmcl/java/JavaInfo.java:104
}
public static <F, E extends ArchiveEntry> JavaInfo fromArchive(ArchiveFileTree<F, E> tree) throws IOException {
if (tree.getRoot().getSubDirs().size() != 1 || !tree.getRoot().getFiles().isEmpty())
throw new IOException();
ArchiveFileTree.Dir<E> jdkRoot = tree.getRoot().getSubDirs().values().iterator().next();
E releaseEntry = jdkRoot.getFiles().get("release");
if (releaseEntry == null)
throw new IOException("Missing release file");
JavaInfo info;
try (BufferedReader reader = new BufferedReader(new InputStreamReader(tree.getInputStream(releaseEntry), StandardCharsets.UTF_8))) {
info = JavaInfo.fromReleaseFile(reader);
}
ArchiveFileTree.Dir<E> binDir = jdkRoot.getSubDirs().get("bin");
if (binDir == null || binDir.getFiles().get(info.getPlatform().getOperatingSystem().getJavaExecutable()) == null)
throw new IOException("Missing java executable file");
return info;
}
public static String normalizeVendor(String vendor) {
if (vendor == null)
return null;
return switch (vendor) {
case "N/A" -> null;
case "Oracle Corporation" -> "Oracle";
case "Azul Systems, Inc." -> "Azul";
case "IBM Corporation", "International Business Machines Corporation", "Eclipse OpenJ9" -> "IBM";
case "Eclipse Adoptium" -> "Adoptium";
case "Amazon.com Inc." -> "Amazon";
default -> vendor;
};
}View on GitHub (pinned to 24702dc5a0)