@@ -78,12 +78,18 @@ The latter two commands should return something like:
78
78
79
79
> /usr/lib/jvm/java-11-openjdk-amd64/lib
80
80
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
+
81
87
## License
82
88
83
89
At your option, under:
84
90
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> )
87
93
88
94
*/
89
95
@@ -96,6 +102,9 @@ use glob::{glob, Pattern};
96
102
97
103
pub mod errors;
98
104
105
+ const JAVA_BINARY : & str = "java" ;
106
+ const JAVAC_BINARY : & str = "javac" ;
107
+
99
108
/// Returns the name of the jvm dynamic library:
100
109
///
101
110
/// * libjvm.so for Linux
@@ -120,16 +129,26 @@ pub fn get_jvm_dyn_lib_file_name() -> &'static str {
120
129
/// If `JAVA_HOME` is not defined, the function tries to locate it using the `java` executable.
121
130
pub fn locate_java_home ( ) -> Result < String > {
122
131
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 ( ) ,
124
133
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 )
126
145
}
127
146
}
128
147
129
148
#[ cfg( target_os = "windows" ) ]
130
- fn do_locate_java_home ( ) -> Result < String > {
149
+ fn do_locate_java_home ( binary : & str ) -> Result < String > {
131
150
let output = Command :: new ( "where" )
132
- . arg ( "java" )
151
+ . arg ( binary )
133
152
. output ( )
134
153
. map_err ( |e| JavaLocatorError :: new ( format ! ( "Failed to run command `where` ({e})" ) ) ) ?;
135
154
@@ -182,9 +201,9 @@ fn do_locate_java_home() -> Result<String> {
182
201
}
183
202
184
203
#[ 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 > {
186
205
let output = Command :: new ( "which" )
187
- . arg ( "java" )
206
+ . arg ( binary )
188
207
. output ( )
189
208
. map_err ( |e| JavaLocatorError :: new ( format ! ( "Failed to run command `which` ({e})" ) ) ) ?;
190
209
let java_exec_path = std:: str:: from_utf8 ( & output. stdout ) ?. trim ( ) ;
@@ -196,17 +215,6 @@ fn do_locate_java_home() -> Result<String> {
196
215
home_path. pop ( ) ;
197
216
home_path. pop ( ) ;
198
217
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
-
210
218
home_path
211
219
. into_os_string ( )
212
220
. into_string ( )
@@ -285,12 +293,19 @@ mod unit_tests {
285
293
286
294
#[ test]
287
295
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
+ ) ;
289
304
}
290
305
291
306
#[ test]
292
307
fn jni_headers_test ( ) {
293
- let java_home = do_locate_java_home ( ) . unwrap ( ) ;
308
+ let java_home = locate_java_home_with_fallback ( ) . unwrap ( ) ;
294
309
assert ! ( PathBuf :: from( java_home)
295
310
. join( "include" )
296
311
. join( "jni.h" )
0 commit comments