diff --git a/Makefile b/Makefile
index 7b1294f98..837f1381d 100644
--- a/Makefile
+++ b/Makefile
@@ -67,7 +67,7 @@ DIRECT_TESTS += \
cpp_siof \
cpp_starvation \
cpp_uninit \
-
+
ifneq ($(BUCK),no)
BUILD_SYSTEMS_TESTS += buck_blacklist buck-clang-db buck_flavors buck_flavors_run buck_flavors_deterministic
@@ -124,6 +124,9 @@ BUILD_SYSTEMS_TESTS += \
resource_leak_exception_lines \
racerd_dedup
+#TODO T41549034: Jdk11 translates string append differently, causing
+#test failures in NullPointerExceptions:stringVarEqualsFalseNPE
+
DIRECT_TESTS += \
java_bufferoverrun \
java_checkers \
@@ -142,6 +145,9 @@ DIRECT_TESTS += \
ifneq ($(ANT),no)
BUILD_SYSTEMS_TESTS += ant
endif
+
+
+
ifneq ($(BUCK),no)
BUILD_SYSTEMS_TESTS += buck genrule buck_javac_jar
# Introduce the dependency only if the two tests are going to be built in parallel, so that they do
diff --git a/Makefile.autoconf.in b/Makefile.autoconf.in
index 7bab83cd3..575e57354 100644
--- a/Makefile.autoconf.in
+++ b/Makefile.autoconf.in
@@ -39,6 +39,7 @@ INSTALL_PROGRAM = @INSTALL_PROGRAM@
IS_FACEBOOK_TREE = @IS_FACEBOOK_TREE@
IS_RELEASE_TREE = @IS_RELEASE_TREE@
JAVAC = @JAVAC@
+JDK11_ENABLED = @JDK11_ENABLED@
LDD = @LDD@
LDFLAGS = @LDFLAGS@
libdir = @libdir@
diff --git a/configure.ac b/configure.ac
index 8653c03d8..53158c6cb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -255,7 +255,13 @@ _ACEOF
rm -f conftest.java
_USER_JAVA_HOME=$($JAVA -cp . conftest)
if rm -f conftest.class; then
- USER_JAVA_HOME=$_USER_JAVA_HOME/..
+ javac_version=`"$JAVAC" -version 2>&1 | head -n 1`
+ [JDK11_ENABLED=`echo "$javac_version" | grep -E -q '^javac\ (11|1[0-9])' && echo yes`]
+ if test "x$JDK11_ENABLED" = "xyes"; then
+ USER_JAVA_HOME=$_USER_JAVA_HOME
+ AC_SUBST([JDK11_ENABLED])
+ else USER_JAVA_HOME=$_USER_JAVA_HOME/..
+ fi
else
AC_MSG_ERROR([Could not run test program with $JAVA])
fi
diff --git a/infer/src/Makefile b/infer/src/Makefile
index d235238d9..02a549952 100644
--- a/infer/src/Makefile
+++ b/infer/src/Makefile
@@ -264,6 +264,7 @@ $(GENERATED_FROM_AUTOCONF): $(MAKEFILE_LIST)
-e 's|@IS_RELEASE_TREE[@]|$(IS_RELEASE_TREE)|g' \
-e "s|@INFER_GIT_COMMIT[@]|$$INFER_GIT_COMMIT|g" \
-e "s|@INFER_GIT_BRANCH[@]|$$INFER_GIT_BRANCH|g" \
+ -e "s|@JDK11_ENABLED[@]|$(JDK11_ENABLED)|g" \
-e "s|@BUILD_C_ANALYZERS[@]|$(BUILD_C_ANALYZERS)|g" \
-e "s|@BUILD_JAVA_ANALYZERS[@]|$(BUILD_JAVA_ANALYZERS)|g" \
-e "s|@OPAMSWITCH[@]|$(OPAMSWITCH)|g" \
diff --git a/infer/src/base/Version.ml.in b/infer/src/base/Version.ml.in
index 21c4ccecd..5ef95a093 100644
--- a/infer/src/base/Version.ml.in
+++ b/infer/src/base/Version.ml.in
@@ -43,6 +43,8 @@ let clang_enabled = is_yes "@BUILD_C_ANALYZERS@"
let java_enabled = is_yes "@BUILD_JAVA_ANALYZERS@"
+let is_jdk11 = is_yes "@JDK11_ENABLED@"
+
let xcode_enabled = is_not_no "@XCODE_SELECT@"
let man_pages_last_modify_date = "@INFER_MAN_LAST_MODIFIED@"
diff --git a/infer/src/base/Version.mli b/infer/src/base/Version.mli
index bfaf9146c..eb3cd0e94 100644
--- a/infer/src/base/Version.mli
+++ b/infer/src/base/Version.mli
@@ -23,6 +23,8 @@ val clang_enabled : bool
val java_enabled : bool
+val is_jdk11 : bool
+
val xcode_enabled : bool
val man_pages_last_modify_date : string
diff --git a/infer/src/integration/Maven.ml b/infer/src/integration/Maven.ml
index 8792cd59b..2f7914a23 100644
--- a/infer/src/integration/Maven.ml
+++ b/infer/src/integration/Maven.ml
@@ -28,13 +28,15 @@ let infer_profile =
true
true
%s
+ %s
|}
infer_profile_name
- (Config.bin_dir ^/ InferCommand.infer_exe_name))
+ (Config.bin_dir ^/ InferCommand.infer_exe_name)
+ (if Version.is_jdk11 then " 11" else ""))
let pom_worklist = ref [CLOpt.init_work_dir]
diff --git a/infer/src/java/jClasspath.ml b/infer/src/java/jClasspath.ml
index 00b1bd81a..af23589dc 100644
--- a/infer/src/java/jClasspath.ml
+++ b/infer/src/java/jClasspath.ml
@@ -115,14 +115,16 @@ let load_from_verbose_output javac_verbose_out =
let file_in = In_channel.create javac_verbose_out in
let class_filename_re =
Str.regexp
- (Printf.sprintf
- (* the unreadable regexp below captures 3 possible forms:
+ ( if Version.is_jdk11 then "\\[wrote \\(.*\\)\\]"
+ else
+ Printf.sprintf
+ (* the unreadable regexp below captures 3 possible forms:
1. [wrote DirectoryFileObject[/path/to/classes_out:path/to/File.java]], leaves `path/to/File.java` in match group 2
2. [wrote RegularFileObject[path/to/File.java]], leaves `path/to/File.java` in match group 5
3. [wrote SimpleFileObject[path/to/File.java]], also leaves `path/to/File.java` in match group 5 *)
- "\\[wrote \
- \\(DirectoryFileObject\\[%s:\\(.*\\)\\|\\(\\(Regular\\|Simple\\)FileObject\\[\\(.*\\)\\)\\)\\]\\]"
- Config.javac_classes_out)
+ "\\[wrote \
+ \\(DirectoryFileObject\\[%s:\\(.*\\)\\|\\(\\(Regular\\|Simple\\)FileObject\\[\\(.*\\)\\)\\)\\]\\]"
+ Config.javac_classes_out )
in
let source_filename_re =
Str.regexp "\\[parsing started \\(Regular\\|Simple\\)FileObject\\[\\(.*\\)\\]\\]"
@@ -137,9 +139,11 @@ let load_from_verbose_output javac_verbose_out =
| line ->
if Str.string_match class_filename_re line 0 then
let path =
- try Str.matched_group 5 line with Caml.Not_found ->
- (* either matched group 5 is found, or matched group 2 is found, see doc for [class_filename_re] above *)
- Config.javac_classes_out ^/ Str.matched_group 2 line
+ if Version.is_jdk11 then Str.matched_group 1 line
+ else
+ try Str.matched_group 5 line with Caml.Not_found ->
+ (* either matched group 5 is found, or matched group 2 is found, see doc for [class_filename_re] above *)
+ Config.javac_classes_out ^/ Str.matched_group 2 line
in
match Javalib.extract_class_name_from_file path with
| exception (JBasics.Class_structure_error _ | Invalid_argument _) ->
diff --git a/infer/src/quandary/JavaTrace.ml b/infer/src/quandary/JavaTrace.ml
index 8b140d7c4..d5ab50a76 100644
--- a/infer/src/quandary/JavaTrace.ml
+++ b/infer/src/quandary/JavaTrace.ml
@@ -544,6 +544,9 @@ module JavaSanitizer = struct
let method_name = Typ.Procname.Java.get_method java_pname in
let sanitizer_matching_supertype typename =
match (Typ.Name.name typename, method_name) with
+ (* string concatenation is translated differently by invokedynamic in JDK11 *)
+ | "java.lang.Object", "makeConcatWithConstants" when Version.is_jdk11 ->
+ Some StringConcatenation
| "java.lang.StringBuilder", "append" ->
Some StringConcatenation
| class_name, method_name ->
diff --git a/infer/tests/build_systems/codetoanalyze/mvn/app_with_infer_profile/pom.xml b/infer/tests/build_systems/codetoanalyze/mvn/app_with_infer_profile/pom.xml
index 0709b1e90..563570d2e 100644
--- a/infer/tests/build_systems/codetoanalyze/mvn/app_with_infer_profile/pom.xml
+++ b/infer/tests/build_systems/codetoanalyze/mvn/app_with_infer_profile/pom.xml
@@ -14,6 +14,7 @@
org.apache.maven.plugins
maven-compiler-plugin
+ 3.8.0
javac
true
diff --git a/infer/tests/codetoanalyze/java/classloads/Makefile b/infer/tests/codetoanalyze/java/classloads/Makefile
index 441986531..c91db0de7 100644
--- a/infer/tests/codetoanalyze/java/classloads/Makefile
+++ b/infer/tests/codetoanalyze/java/classloads/Makefile
@@ -47,9 +47,15 @@ infer-out/report.json: $(JAVA_DEPS) $(SOURCES) $(MAKEFILE_LIST)
$(JAVAC) -cp $(CLASSPATH) $(SOURCES))
%.loads: %.class
+ifeq ($(JDK11_ENABLED),yes)
+ $(QUIET)java -verbose:class $* | grep "\[info\]\[class,load\]" | cut -f2 -d' ' | grep -vE "^(java|sun|jdk|opened:)" > $@
+else
$(QUIET)java -verbose:class $* | grep "^\[Loaded" | cut -f2 -d' ' | grep -vE "^(java|sun)" > $@
+endif
+
loads.exp: $(LOADS)
+
$(QUIET)for F in $(LOADS) ; do sed -e "s#^#$(TEST_REL_DIR)/$${F%.*}.java, #" $$F ; done | sort > loads.exp
loads.exp.test: issues.exp.test$(TEST_SUFFIX)