[Java/JDK] 通过命令行执行JAR包中指定Java类的main方法
1 概述:通过命令行执行JAR包中指定Java类的main方法
- 要通过命令行执行JAR包中任意指定类的
main方法,你需要了解JAR包的结构并正确使用Java命令行工具。以下是实现方法:
基本方法
java -cp your-jar-file.jar com.example.YourMainClass
其中:
-cp或-classpath参数指定类路径(可以是JAR文件或目录)com.example.YourMainClass是你要执行的主类的完整限定名
详细步骤
- 确保JAR包是可执行的
虽然不是必须的,但有助于理解:
可执行的JAR包通常在MANIFEST.MF中指定了Main-Class
但我们这里要执行任意类,所以不需要依赖这个设置
- 执行任意类的
main方法:
java -cp your-application.jar com.your.package.MainClass arg1 arg2
处理依赖
- 如果你的JAR有依赖其他JAR文件:
- Windows系统
java -cp "your-jar-file.jar;lib/*" com.example.YourMainClass
- Linux/Mac系统
java -cp "your-jar-file.jar:lib/*" com.example.YourMainClass
创建可执行脚本
为了方便使用,可以创建一个脚本文件:
- Windows (run.bat)
@echo off
java -cp "your-app.jar;lib/*" %1 %*
- Linux/Mac (run.sh)
#!/bin/bash
java -cp "your-app.jar:lib/*" "$1" "${@:2}"
然后使用方式:
./run.sh com.example.YourMainClass arg1 arg2
- 使用jar命令查看JAR内容
如果不确定JAR中包含哪些类,可以先查看:
jar tf your-jar-file.jar
或者查找包含"Main"的类:
jar tf your-jar-file.jar | grep -i main
注意事项
- 确保指定的类确实有
public static void main(String[] args)方法
- 类名必须包含完整的包路径
- 如果类在某个包中,必须使用完全限定名(包括包名)
在Windows上,类路径分隔符是分号(
;),在Linux/Mac上是冒号(:)
- 示例
假设有一个JAR文件
myApp.jar,其中包含类com.example.tools.DataProcessor,你想用参数input.txt和output.txt执行它:
java -cp myapp.jar com.example.tools.DataProcessor input.txt output.txt
通过这种方式,你可以灵活地执行JAR包中的任何可执行类,而不局限于
MANIFEST.MF中指定的主类。
Z 最佳实践
CASE 基于胖JAR包,指定目标类执行
胖包的好处: 只需1个JAR包(所有依赖都在这个JAR包内部了),无需再单独引入其他依赖。
打胖包的插件
pom.xml
<project>
<properties>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<maven-compiler-plugin.version>3.13.0</maven-compiler-plugin.version>
<maven-assembly-plugin.version>3.4.2</maven-assembly-plugin.version>
<application.startupClass>com.xxx.sdk.helper.SdkHelper</application.startupClass>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>${maven-assembly-plugin.version}</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<!--
<descriptors>
<descriptor>src/main/assembly/assembly.xml</descriptor>
</descriptors>
-->
<archive>
<manifest>
<!-- 声明入口主类 [可选] -->
<mainClass>${application.startupClass}</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
<!--<encoding>${project.build.outputEncoding}</encoding>-->
<!-- <skipTests>true</skipTests> --><!-- 跳过测试 -->
<!--<verbose>true</verbose>--> <!--<showWarnings>true</showWarnings>--> <!--<fork>true</fork>--><!-- 要使compilerVersion标签生效,还需要将fork设为true,用于明确表示编译版本配置的可用 -->
<!--<executable>--><!-- path-to-javac --><!--</executable>--><!-- 使用指定的javac命令,例如:<executable>${JAVA_1_4_HOME}/bin/javac</executable> -->
<!--<compilerVersion>${java.version}</compilerVersion>--><!-- 指定插件将使用的编译器的版本 -->
<!--<meminitial>128m</meminitial>--><!-- 编译器使用的初始内存 -->
<!--<maxmem>512m</maxmem>--><!-- 编译器使用的最大内存 -->
<!--<compilerArgument>-verbose -bootclasspath ${java.home}\lib\rt.jar</compilerArgument>--><!-- 这个选项用来传递编译器自身不包含但是却支持的参数选项 -->
</configuration>
</plugin>
</plugins>
</build>
</project>
Demo
HelloWorld
package com.xxx.sdk.helper;
import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class HelloWorld {
/**
* @usage
* java -cp "xxx-sdk-helper-1.0.0-SNAPSHOT-jar-with-dependencies.jar" com.xxx.sdk.helper.SdkHelper "com.xxx.sdk.helper.HelloWorld"
* java -cp "xxx-sdk-helper-1.0.0-SNAPSHOT-jar-with-dependencies.jar" "com.xxx.sdk.helper.HelloWorld" "hello"
* @param args
*/
public static void main( String[] args ) {
/**
* 通过命令行执行指定的 Java Class
*/
log.info("Hello world!args({}):{}", args.length, JSON.toJSONString(args));
}
}
SdkHelper
package com.xxx.sdk.helper;
import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.Method;
import java.util.Arrays;
/**
* SDK 使用助手
*/
@Slf4j
public class SdkHelper {
public static void main( String[] args ) {
/**
* 通过命令行执行指定的 Java Class
*/
log.info("args:{}", JSON.toJSONString(args));
String className = args[0];
try {
Class<?> clazz = Class.forName(className);
Method method = clazz.getMethod("main", String[].class);
log.info("method.parameterCount:{}", method.getParameterCount());
//创建目标对象
Object targetObject = clazz.newInstance();
String [] args2 = Arrays.copyOfRange(args, 1, args.length);
method.invoke(targetObject, new Object [] { args2 } );
} catch (Exception exception) {
log.error("Fail to execute target class method!exception:", exception);
}
}
}
- 使用示例
- 示例1
java -cp "xxx-sdk-helper-1.0.0-SNAPSHOT-jar-with-dependencies.jar" com.xxx.sdk.helper.SdkHelper "com.xxx.sdk.helper.HelloWorld" "Hello"
out
[2025/07/22 10:46:33.851] [INFO ] [main] [com.xxx.sdk.helper.SdkHelper :18 main] args:["com.xxx.sdk.helper.SdkHelper","com.xxx.sdk.helper.HelloWorld","Hello"]
[2025/07/22 10:46:33.856] [INFO ] [main] [com.xxx.sdk.helper.SdkHelper :23 main] method.parameterCount:1
[2025/07/22 10:46:33.857] [INFO ] [main] [com.xxx.sdk.helper.SdkHelper :18 main] args:["com.xxx.sdk.helper.HelloWorld","Hello"]
[2025/07/22 10:46:33.858] [INFO ] [main] [com.xxx.sdk.helper.SdkHelper :23 main] method.parameterCount:1
[2025/07/22 10:46:33.859] [INFO ] [main] [com.xxx.sdk.helper.HelloWorld :18 main] Hello world!args(1):["Hello"]
- 示例2
java -cp "xxx-sdk-helper-1.0.0-SNAPSHOT-jar-with-dependencies.jar" "com.xxx.sdk.helper.HelloWorld" "Hello"
out
[2025/07/22 10:48:54.641] [INFO ] [main] [com.xxx.sdk.helper.HelloWorld :18 main] Hello world!args(2):["com.xxx.sdk.helper.HelloWorld","hello"]
Y 推荐文献
- [JVM] 概念辨析:classpath / jar - 博客园/千千寰宇
- [Linux/Java SE] 反编译:查看JAR包内的类 | JAR 命令 | 反编译 | JD-GUI | JD-CORE - 博客园/千千寰宇
X 参考文献
本文作者:
千千寰宇
本文链接: https://www.cnblogs.com/johnnyzen
关于博文:评论和私信会在第一时间回复,或直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
日常交流:大数据与软件开发-QQ交流群: 774386015 【入群二维码】参见左下角。您的支持、鼓励是博主技术写作的重要动力!
本文链接: https://www.cnblogs.com/johnnyzen
关于博文:评论和私信会在第一时间回复,或直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
日常交流:大数据与软件开发-QQ交流群: 774386015 【入群二维码】参见左下角。您的支持、鼓励是博主技术写作的重要动力!

浙公网安备 33010602011771号