@@ -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
8389At 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
97103pub 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.
121130pub 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