Explain Codes LogoExplain Codes Logo

How to run a class from Jar which is not the Main-Class in its Manifest file

java
classpath
reflection
spring-boot
Anton ShumikhinbyAnton Shumikhin·Nov 11, 2024
TLDR

To run a class that isn't identified as the Main-Class in a JAR's manifest, assign the class directly:

java -cp YourJar.jar com.yourpackage.YourClass

Make sure the classpath (-cp) includes your JAR and substitute com.yourpackage.YourClass with the class you intend to execute.

Managing dependencies and classpath structure

When your desired class within the JAR depends on other classes or external libraries, it's crucial to include all dependencies in the classpath. In case your JAR gets built via Maven, a lib directory is typically generated with the required dependencies. To include these, use:

java -cp "YourJar.jar;lib/*" com.yourpackage.YourClass

// Here, ";" is more like a classpath party separator rather than a path separator 😅

For UNIX-like systems, utilize a colon : instead of a semicolon ;.

Decoding the error messages

Executing a class may occasionally lead to errors. Here are some potential workarounds:

  • Confirm that class and package names don't have any typos.
  • Verify the desired class includes a static main method with the required signature public static void main(String[] args).
  • Double-check if the classpath includes all necessary JAR files and directories.

Spring Boot executions

Spring Boot applications require a different approach. Instead of using the traditional java -jar option, make use of the PropertiesLauncher:

java -cp YourJar.jar -Dloader.main=com.yourpackage.YourClass org.springframework.boot.loader.PropertiesLauncher

The -Dloader.main property instructs the Spring Boot's loader to switch the main class. Always ensure that you're packaging the application correctly:

mvn package spring-boot:repackage

Advanced execution techniques

Developing a dispatcher class

Dynamically choosing the class to run may be necessary. A dispatcher class within the JAR would take input arguments and dynamically invoke the main method of the intended class using reflection.

Here's a taste of what a dispatcher could look like:

public class Dispatcher { public static void main(String[] args) throws Exception { Class<?> clazz = Class.forName(args[0]); Method method = clazz.getMethod("main", String[].class); // It's like whispering to the method, "Hey, it's time to wake up!" String[] mainArgs = Arrays.copyOfRange(args, 1, args.length); method.invoke(null, (Object) mainArgs); } }

Utilizing wrapper JARs

For a sustainable solution, create a wrapper JAR, which includes the main JAR in its Class-Path attribute within its Manifest. This wrapper JAR can specify different main classes and relay the arguments appropriately.