fix: stop rejecting java installations over an awt probe
This commit is contained in:
parent
84d1cf558c
commit
09073319b1
5 changed files with 7 additions and 131 deletions
Binary file not shown.
|
|
@ -1,6 +1,3 @@
|
|||
import java.io.File;
|
||||
import java.util.Locale;
|
||||
|
||||
public final class JavaInfo {
|
||||
private static final String[] CHECKED_PROPERTIES = new String[] {"os.arch", "java.version", "java.vendor", "java.home"};
|
||||
|
||||
|
|
@ -17,77 +14,11 @@ public final class JavaInfo {
|
|||
}
|
||||
}
|
||||
|
||||
System.out.println("java.awt=" + hasClass("java.awt.Toolkit"));
|
||||
System.out.println("java.awt.natives=" + hasAwtNatives());
|
||||
System.out.println("java.awt.link=" + awtLinks());
|
||||
System.out.println("java.jdk=" + hasCompiler());
|
||||
|
||||
System.exit(returnCode);
|
||||
}
|
||||
|
||||
/** Loads the class without initialising it, so no display is ever needed. */
|
||||
private static boolean hasClass(String name) {
|
||||
try {
|
||||
Class.forName(name, false, JavaInfo.class.getClassLoader());
|
||||
return true;
|
||||
} catch (Throwable ignored) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasAwtNatives() {
|
||||
try {
|
||||
String os = System.getProperty("os.name", "").toLowerCase(Locale.ROOT);
|
||||
String[] required;
|
||||
|
||||
if (os.contains("win")) {
|
||||
required = new String[] {"awt.dll", "fontmanager.dll"};
|
||||
} else if (os.contains("mac") || os.contains("darwin")) {
|
||||
required = new String[] {"libawt_lwawt.dylib", "libfontmanager.dylib"};
|
||||
} else {
|
||||
required = new String[] {"libawt_xawt.so", "libfontmanager.so"};
|
||||
}
|
||||
|
||||
for (String name : required) {
|
||||
if (!findNative(name)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (Throwable ignored) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean findNative(String name) {
|
||||
File home = new File(System.getProperty("java.home", "."));
|
||||
File[] roots = new File[] {
|
||||
new File(home, "lib"),
|
||||
new File(home, "bin"),
|
||||
new File(new File(home, "lib"), System.getProperty("os.arch", "")),
|
||||
};
|
||||
|
||||
for (File root : roots) {
|
||||
if (new File(root, name).isFile()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean awtLinks() {
|
||||
try {
|
||||
java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment().getClass();
|
||||
return true;
|
||||
} catch (LinkageError broken) {
|
||||
return false;
|
||||
} catch (Throwable ignored) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasCompiler() {
|
||||
try {
|
||||
return javax.tools.ToolProvider.getSystemJavaCompiler() != null;
|
||||
|
|
|
|||
|
|
@ -6,8 +6,7 @@ java.vendor=Azul Systems, Inc.
|
|||
```
|
||||
|
||||
> [!NOTE]
|
||||
> The checked-in `JavaInfo.class` predates the `java.home`, `java.awt` and `java.jdk`
|
||||
> lines and does not print them yet. Recompiling it against a Java 8 target
|
||||
> (`javac --release 8 JavaInfo.java`) is what turns the probe-side answers on; until
|
||||
> then [`checker.rs`](../../src/checker.rs) falls back to inspecting the installation
|
||||
> on disk, which reaches the same verdict for every image seen in the wild.
|
||||
> `JavaInfo.class` is checked in rather than built, so recompile it against a Java 8
|
||||
> target (`javac -source 8 -target 8 JavaInfo.java`) whenever the source changes,
|
||||
> and commit both files together. [`checker.rs`](../../src/checker.rs) reads only the
|
||||
> `key=value` lines it prints.
|
||||
|
|
|
|||
|
|
@ -68,18 +68,6 @@ pub async fn check_java_runtime(absolute_path: String) -> JavaResult<JavaCheckIn
|
|||
return Err(JavaError::InvalidJavaPath { path: absolute_path });
|
||||
};
|
||||
|
||||
// Minecraft needs AWT a headless image launches fine and then dies mid-game
|
||||
if !has_usable_awt(&info) {
|
||||
tracing::warn!(
|
||||
path = %absolute_path,
|
||||
classes = probe_flag(&info, "java.awt"),
|
||||
natives = probe_flag(&info, "java.awt.natives"),
|
||||
links = probe_flag(&info, "java.awt.link"),
|
||||
"java installation has no usable java.awt support"
|
||||
);
|
||||
return Err(JavaError::MissingAwtSupport { path: absolute_path });
|
||||
}
|
||||
|
||||
Ok(JavaCheckInfo {
|
||||
os_arch: info
|
||||
.get("os.arch")
|
||||
|
|
@ -94,12 +82,6 @@ pub async fn check_java_runtime(absolute_path: String) -> JavaResult<JavaCheckIn
|
|||
})
|
||||
}
|
||||
|
||||
fn has_usable_awt(info: &HashMap<String, String>) -> bool {
|
||||
probe_flag(info, "java.awt")
|
||||
&& probe_flag(info, "java.awt.natives")
|
||||
&& probe_flag(info, "java.awt.link")
|
||||
}
|
||||
|
||||
fn probe_flag(info: &HashMap<String, String>, key: &str) -> bool {
|
||||
info.get(key)
|
||||
.is_some_and(|value| value.eq_ignore_ascii_case("true"))
|
||||
|
|
@ -136,42 +118,12 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn a_flag_the_probe_never_printed_is_false() {
|
||||
assert!(!probe_flag(&info(&[]), "java.awt"));
|
||||
assert!(!probe_flag(&info(&[]), "java.jdk"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_flag_is_read_regardless_of_case() {
|
||||
assert!(probe_flag(&info(&[("java.awt", "TRUE")]), "java.awt"));
|
||||
assert!(!probe_flag(&info(&[("java.awt", "false")]), "java.awt"));
|
||||
}
|
||||
|
||||
fn awt(classes: &str, natives: &str, link: &str) -> HashMap<String, String> {
|
||||
info(&[
|
||||
("java.awt", classes),
|
||||
("java.awt.natives", natives),
|
||||
("java.awt.link", link),
|
||||
])
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_complete_image_is_usable() {
|
||||
assert!(has_usable_awt(&awt("true", "true", "true")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn awt_classes_without_their_natives_are_not_usable() {
|
||||
assert!(!has_usable_awt(&awt("true", "false", "true")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn natives_that_refuse_to_link_are_not_usable() {
|
||||
assert!(!has_usable_awt(&awt("true", "true", "false")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn every_half_is_required() {
|
||||
assert!(!has_usable_awt(&info(&[("java.awt", "true")])));
|
||||
assert!(!has_usable_awt(&info(&[("java.awt.natives", "true")])));
|
||||
assert!(!has_usable_awt(&info(&[("java.awt.link", "true")])));
|
||||
assert!(probe_flag(&info(&[("java.jdk", "TRUE")]), "java.jdk"));
|
||||
assert!(!probe_flag(&info(&[("java.jdk", "false")]), "java.jdk"));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,11 +41,6 @@ pub enum JavaError {
|
|||
#[error("selected path is not a valid java installation: {path}")]
|
||||
InvalidJavaPath { path: String },
|
||||
|
||||
#[error(
|
||||
"java installation at '{path}' has no usable java.awt (the java.desktop module or its native libraries are missing)"
|
||||
)]
|
||||
MissingAwtSupport { path: String },
|
||||
|
||||
#[error("selected java is version {found}, but version {expected} is required")]
|
||||
VersionMismatch { expected: u32, found: u32 },
|
||||
|
||||
|
|
@ -68,7 +63,6 @@ impl JavaError {
|
|||
matches!(
|
||||
self,
|
||||
JavaError::InvalidJavaPath { .. }
|
||||
| JavaError::MissingAwtSupport { .. }
|
||||
| JavaError::ParseVersion { .. }
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue