plexus-compiler icon indicating copy to clipboard operation
plexus-compiler copied to clipboard

JavacCompiler fails to resolve version with maven toolchains and Jenkins

Open nxglhez opened this issue 1 year ago • 2 comments

Hello,

When maven-compiler-plugin is configured to fork or use a toolchains, Plexus JavacCompiler fails to determine correctly the Java version if there is a JAVA_TOOL_OPTIONS set prior, which is done automatically by Jenkins (I can't remove it): problem is that if affect the encoding as well as other parts (mostly in buildCompilerArguments) because it badly interpret the Java version to 1.3 (in my case).

The method getOutOfProcessJavacVersion use javac -version to determine compiler version, then it use use a regexp \d+(\.\d+)? on the stdout but when JAVA_TOOL_OPTIONS, there is an (annoying) warning and if the warning contains something that match the regexp, such as ... as version, it fails to return the proper JDK version:

Picked up JAVA_TOOL_OPTIONS: -Dmaven.ext.class.path="/some/path/with/name-1.3.x/foobar.jar" -Dorg.jenkinsci.plugins.pipeline.maven.reportsFolder="/some/path/with/name-1.3.x/"
javac 1.8.0_432

The regex can be tested here: https://regex101.com/r/EboVGM/1

As we can see, we have more than one result:

  • 1.3 <-- selected
  • 1.3
  • 1.8
  • 0
  • 432

If you are lucky, and like most Linux, javac will use UTF-8 while compiling: you won't notice anything.

If you are unlucky (like me), javac will not use UTF-8 while compiling, but ANSI_X3.4-1968 and it fails at the first mappable character it found (like ©).

One fix to this issue would be to resolve version from the javac line only:

String prefix = "javac ";
int prefixLength = prefix.length();
// grab the "javac " part
Optional<String> javacPrefix = Arrays.stream(text.split("\\R"))
      .filter(line -> line.startsWith(prefix))
      .map(line -> line.substring(prefixLength))
      .findFirst();
return javacPrefix.map(line -> JAVA_MAJOR_AND_MINOR_VERSION_PATTERN.matcher(line))
                  .filter(Matcher::find)
                  .map(Matcher::group)
                  .orElseThrow(() -> "Could not extract version from \"" + text + "\"");

Or we could assume that javac is always last and process only last line:

String[] lines = text.split("\\R");
String  lastLine = lines.length == 0 ? "":lines[lines.length-1];

Note: JAVA_TOOL_OPTIONS is set by Jenkins withMaven for various reasons and the docs indicate it is not possible to avoid this warning: https://github.com/jenkinsci/pipeline-maven-plugin/blob/master/FAQ.adoc#why-do-i-see-messages-warning-picked-up-java_tool_options-in-the-build-logs

When using the JAVA_TOOL_OPTIONS, the JVM outputs a message during its initialization.

nxglhez avatar Nov 19 '24 14:11 nxglhez

Need more fixes for JDK 8

slawekjaranowski avatar Nov 10 '25 18:11 slawekjaranowski

Similar in m-jar-p

  • https://github.com/apache/maven-jar-plugin/pull/500

slawekjaranowski avatar Nov 10 '25 21:11 slawekjaranowski