Skip to content

Commit 5532531

Browse files
Update to new fix implementation
1 parent cb11989 commit 5532531

File tree

3 files changed

+40
-25
lines changed

3 files changed

+40
-25
lines changed

.github/workflows/ci-workflow.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ jobs:
2929
- name: Test Rust with Cargo
3030
run: cargo test --verbose -- --nocapture
3131

32-
test-legacy:
32+
# This is a good test for the locate-jdk-only feature, as the JRE is in a different path on JDK 8
33+
test-locate-jdk:
3334
runs-on: ubuntu-latest
34-
3535
steps:
3636
- uses: actions/checkout@v4
3737
- name: Set up JDK 8
@@ -40,4 +40,4 @@ jobs:
4040
java-version: '8'
4141
distribution: 'temurin'
4242
- name: Test Rust with Cargo
43-
run: JAVA_HOME="" cargo test --features=legacy-java-compat --verbose -- --nocapture
43+
run: JAVA_HOME="" cargo test --features=locate-jdk-only --verbose -- --nocapture

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,4 @@ docopt = { version = "1.1", optional = true }
2727

2828
[features]
2929
build-binary = ["docopt"]
30-
legacy-java-compat = []
30+
locate-jdk-only = []

src/lib.rs

Lines changed: 36 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -78,12 +78,18 @@ The latter two commands should return something like:
7878
7979
> /usr/lib/jvm/java-11-openjdk-amd64/lib
8080
81+
## Extra Features
82+
83+
* `locate-jdk-only`: Attempts to locate the JDK first by searching for the Java compiler. \
84+
If this fails, it falls back to locating the JRE by searching for the Java runtime.
85+
This solves issues in JDK 8 where the JRE resides in a subdirectory and not in the JDK root.
86+
8187
## License
8288
8389
At your option, under:
8490
85-
* Apache License, Version 2.0, (http://www.apache.org/licenses/LICENSE-2.0)
86-
* MIT license (http://opensource.org/licenses/MIT)
91+
* Apache License, Version 2.0, (<http://www.apache.org/licenses/LICENSE-2.0>)
92+
* MIT license (<http://opensource.org/licenses/MIT>)
8793
8894
*/
8995

@@ -96,6 +102,9 @@ use glob::{glob, Pattern};
96102

97103
pub mod errors;
98104

105+
const JAVA_BINARY: &str = "java";
106+
const JAVAC_BINARY: &str = "javac";
107+
99108
/// Returns the name of the jvm dynamic library:
100109
///
101110
/// * libjvm.so for Linux
@@ -120,16 +129,26 @@ pub fn get_jvm_dyn_lib_file_name() -> &'static str {
120129
/// If `JAVA_HOME` is not defined, the function tries to locate it using the `java` executable.
121130
pub fn locate_java_home() -> Result<String> {
122131
match &env::var("JAVA_HOME") {
123-
Ok(s) if s.is_empty() => do_locate_java_home(),
132+
Ok(s) if s.is_empty() => locate_java_home_with_fallback(),
124133
Ok(java_home_env_var) => Ok(java_home_env_var.clone()),
125-
Err(_) => do_locate_java_home(),
134+
Err(_) => locate_java_home_with_fallback(),
135+
}
136+
}
137+
138+
fn locate_java_home_with_fallback() -> Result<String> {
139+
if cfg!(feature = "locate-jdk-only") {
140+
// Try locating the JDK first by searching for the Java compiler
141+
// If this fails, fallback to locating the JRE, by locating the Java runtime
142+
do_locate_java_home(JAVAC_BINARY).or_else(|_| do_locate_java_home(JAVA_BINARY))
143+
} else {
144+
do_locate_java_home(JAVA_BINARY)
126145
}
127146
}
128147

129148
#[cfg(target_os = "windows")]
130-
fn do_locate_java_home() -> Result<String> {
149+
fn do_locate_java_home(binary: &str) -> Result<String> {
131150
let output = Command::new("where")
132-
.arg("java")
151+
.arg(binary)
133152
.output()
134153
.map_err(|e| JavaLocatorError::new(format!("Failed to run command `where` ({e})")))?;
135154

@@ -182,9 +201,9 @@ fn do_locate_java_home() -> Result<String> {
182201
}
183202

184203
#[cfg(not(any(target_os = "windows", target_os = "macos")))] // Unix
185-
fn do_locate_java_home() -> Result<String> {
204+
fn do_locate_java_home(binary: &str) -> Result<String> {
186205
let output = Command::new("which")
187-
.arg("java")
206+
.arg(binary)
188207
.output()
189208
.map_err(|e| JavaLocatorError::new(format!("Failed to run command `which` ({e})")))?;
190209
let java_exec_path = std::str::from_utf8(&output.stdout)?.trim();
@@ -196,17 +215,6 @@ fn do_locate_java_home() -> Result<String> {
196215
home_path.pop();
197216
home_path.pop();
198217

199-
// Java 8(aka 1.8) has a slightly different directory structure,
200-
// where java is in the ${JAVA_HOME}/jre/bin/java directory, and ${JAVA_HOME}/bin/java is just a symlink.
201-
// Since we recursively follow symlinks, we end up in the wrong directory,
202-
// so we need to pop one more time.
203-
#[cfg(feature = "legacy-java-compat")]
204-
if let Some(last_section) = home_path.file_name() {
205-
if last_section == "jre" {
206-
home_path.pop();
207-
}
208-
}
209-
210218
home_path
211219
.into_os_string()
212220
.into_string()
@@ -285,12 +293,19 @@ mod unit_tests {
285293

286294
#[test]
287295
fn locate_java_from_exec_test() {
288-
println!("do_locate_java_home: {}", do_locate_java_home().unwrap());
296+
println!(
297+
"do_locate_java_home: {}",
298+
do_locate_java_home(JAVA_BINARY).unwrap()
299+
);
300+
println!(
301+
"do_locate_java_home: {}",
302+
do_locate_java_home(JAVAC_BINARY).unwrap()
303+
);
289304
}
290305

291306
#[test]
292307
fn jni_headers_test() {
293-
let java_home = do_locate_java_home().unwrap();
308+
let java_home = locate_java_home_with_fallback().unwrap();
294309
assert!(PathBuf::from(java_home)
295310
.join("include")
296311
.join("jni.h")

0 commit comments

Comments
 (0)