🚀 Using multiples JDKs with Maven Toolchains

🚀 Using multiples JDKs with Maven Toolchains

🚀 Have You Ever Needed to Build a Legacy Java Project While Your Team Works on Modern Java?

Have you ever had to maintain a legacy Java project on Java 8 (or an even older version), while another team is already working with the latest Java? Or tried to configure Maven so that everyone compiles the project using the correct JDK version?

There’s a clean, controlled, and professional way to handle this: toolchains.xml in Maven.

💣 The Classic Challenge

By default, Maven uses the JDK defined in your system’s JAVA_HOME. This becomes a problem when:

  • Different projects require different Java versions.
  • CI/CD pipelines must ensure reliable builds using an exact JDK version.
  • You want to isolate your local development environment from the build configuration.


🔧 The Solution: Maven Toolchains

With the Toolchains plugin, you can register all the JDKs installed on your system and specify, per project, which one to use.

Let’s walk through how it works.


📁 1. Defining Your JDKs in ~/.m2/toolchains.xml

<toolchains xmlns="http://maven.apache.org/TOOLCHAINS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/TOOLCHAINS/1.1.0 http://maven.apache.org/xsd/toolchains-1.1.0.xsd">

        <toolchain>
		<type>jdk</type>
		<provides>
			<version>1.8</version>
		</provides>
		<configuration>
			<jdkHome>/usr/lib/jvm/jdk1.6.0_45</jdkHome>
		</configuration>
	</toolchain>
	
        <toolchain>
		<type>jdk</type>
		<provides>
			<version>1.8</version>
		</provides>
		<configuration>
			<jdkHome>/usr/lib/jvm/java-8-openjdk-amd64</jdkHome>
		</configuration>
	</toolchain>

	<toolchain>
		<type>jdk</type>
		<provides>
			<version>17</version>
		</provides>
		<configuration>
			<jdkHome>/usr/lib/jvm/java-17-openjdk-amd64</jdkHome>
		</configuration>
	</toolchain>

	<toolchain>
		<type>jdk</type>
		<provides>
			<version>21</version>
		</provides>
		<configuration>
			<jdkHome>/usr/lib/jvm/java-21-openjdk-amd64</jdkHome>
		</configuration>
	</toolchain>

</toolchains>local machine file        

🧠 This is an example of a local machine file, and it should not be committed to the repository.


⚙️ 2. Configuring pom.xml to Use JDK 17 (and Compile to Java 8)

<build>
    <plugins>
        <!-- Creates JAR with Manifest -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>3.4.2</version>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <classpathPrefix>lib/</classpathPrefix>
                        <mainClass>Main</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>

        <!-- Selects JDK 17 using toolchains -->

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-toolchains-plugin</artifactId>
            <version>3.2.0</version>
            <executions>
                <execution>
                    <goals>
                        <goal>toolchain</goal>
                    </goals>
                </execution>
            </executions>

            <configuration>
                <toolchains>
                    <jdk>
                        <version>17</version>
                    </jdk>
                </toolchains>
            </configuration>
        </plugin>

        <!-- Compiles to Java 8-compatible bytecode -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.10.1</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>
    </plugins>

</build>        

👉 Result: you compile the code using JDK 17, but generate bytecode compatible with Java 8 — perfect for legacy libraries or systems still running on older JVMs.


🎯 Why Is This Powerful ?

  • ✅ Prevents bugs caused by inconsistent compiler environments.
  • ✅ Simplifies team collaboration and CI/CD pipeline management.
  • ✅ Full flexibility to modernize your setup while maintaining backward compatibility.


🧠 Final Takeaways

  • toolchains.xml defines available JDKs on your system.
  • pom.xml specifies which JDK to use for each project.
  • You can build with a modern JDK (like 17 or 21) and still generate bytecode compatible with older versions (like 1.8).


💬 Did You Know About This ?

Have you ever used toolchains.xml with your team? How do you handle multiple JDKs across projects in your environment?

💡 Leave a comment! Let’s share some experiences 👇

📤 If you found this helpful, share it with your team or tag someone who's always wrestling with JAVA_HOME!

#Java #Maven #Toolchains #JDK #BuildAutomation #Backend #DevTips

Great man! This is not unique to maven, but with gradle this is possible too. https://docs.gradle.org/current/userguide/toolchains.html

Like
Reply

This is a fantastic explanation of how to effectively manage legacy Java projects alongside modern Java development! The challenges of maintaining a project on an older Java version while the rest of the team progresses with the latest releases can be daunting. Thanks for sharing this valuable insight!

Like
Reply

Thoughtful post, thanks Max

Like
Reply

Maven Toolchains allow you to manage multiple JDK versions in legacy and modern Java projects, ensuring consistent builds. This solves version conflicts and streamlines development.

To view or add a comment, sign in

More articles by Max Benin

Others also viewed

Explore content categories