java -jar

在Java开发中,我们经常需要将多个类打包成一个可执行的jar文件,以便于分发和运行。 而使用java -jar命令是一种方便快捷地在命令行中运行Java可执行jar文件的方法。本文将详细介绍java -jar命令的使用方式、原理及提供相关的代码演示和案例。通过阅读本文,您将深入了解java -jar命令的背后机制,并能够灵活运用于实际开发项目中。

第一部分:java -jar命令的基本用法及注意事项

1. 找到jar文件(java archive)

首先,我们需要定位要运行的jar文件所在的目录。在命令行中使用"cd"命令来切换到该目录。

2. 运行java -jar命令

运行"java -jar <filename.jar>“命令,其中”<filename.jar>“是要运行的jar文件的名称。确保在命令中提供完整的文件名,包括扩展名”.jar"。

3. 执行主类

运行java -jar命令后,Java虚拟机将加载并执行该jar文件中的主类。确保你的jar文件包含一个可执行的主类,并且该类在Manifest文件中被正确地声明为主类。如果你的jar文件没有正确配置Manifest文件,你可以使用"java -cp <filename.jar> "命令来运行主类。


java -jar命令用于运行可执行的JAR文件。它会自动查找JAR文件中的清单文件MANIFEST.MF),并根据清单文件中的Main-Class属性指定的主类来启动应用程序。

4. 注意事项

  • 确保已经安装了Java Development Kit (JDK)并设置了正确的环境变量。
  • 在使用java -jar命令时,请确保jar文件是可执行的,并且包含了所需的依赖库。
  • 如果jar文件需要传递参数,可以在java -jar命令后添加相应的参数。

第二部分:java -jar命令的原理解析

1. jar文件的结构

jar文件实际上是一个压缩文件,类似于zip文件。它包含了Java类文件、资源文件和配置文件等。可以使用"jar tf <filename.jar>"命令来查看jar文件的内容。

2. Manifest文件

Manifest文件是jar文件的一个重要组成部分,它记录了jar文件的元数据,包括主类、依赖库等信息。通过在Manifest文件中指定主类,Java虚拟机能够正确地加载和执行jar文件中的主类。

3. Class-Path属性

在Manifest文件中,可以使用Class-Path属性来指定jar文件的依赖库。Java虚拟机将根据Class-Path属性来加载所需的依赖库。

4. 执行流程

当我们使用java -jar命令运行jar文件时,Java虚拟机会按照以下顺序进行操作:

  • 解析Manifest文件,获取主类信息。
  • 加载主类及其依赖的类。
  • 执行主类的main方法。

第三部分:代码演示和案例

下面通过一个简单的案例来演示java -jar命令的使用。

假设我们有一个名为"HelloWorld"的Java项目,其中包含了一个名为"HelloWorld"的主类。我们希望将该项目打包成一个可执行的jar文件,并通过java -jar命令来运行。

代码示例: 创建项目结构: 在本地创建一个名为"HelloWorld"的文件夹,在该文件夹下创建如下的项目结构:

HelloWorld/
   |--src/
   |     |--com/
   |           |--example/
   |                   |--HelloWorld.java
   |--manifest.mf

编写HelloWorld.java文件,在HelloWorld.java文件中编写如下的Java代码:

package com.example;
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

编写manifest.mf文件:在manifest.mf文件中编写如下的内容:

Manifest-Version: 1.0
Main-Class: com.example.HelloWorld

编译和打包:在命令行中切换到"HelloWorld"文件夹,并执行以下命令来编译和打包项目:

javac -d bin src/com/example/HelloWorld.java
jar -cvfm HelloWorld.jar manifest.mf -C bin .

运行jar文件:在命令行中执行以下命令来运行jar文件:

java -jar HelloWorld.jar

输出结果: 命令行将会输出"Hello, World!"的消息。

第四部分 常用参数详解

以下是一些常用的java -jar命令的参数,让我们逐一了解它们的功能和用法。

  • -Xmx:指定Java堆的最大内存大小。例如,-Xmx512m表示将最大堆内存设置为512MB。通过调整堆内存大小,可以优化应用程序的性能和内存使用情况
  • -Xms:指定Java堆的初始内存大小。例如,-Xms256m表示将初始堆内存设置为256MB。这个参数可以帮助您在启动应用程序时控制初始内存分配的大小
  • -Xss:指定线程栈的大小。例如,-Xss1m表示将线程栈大小设置为1MB。线程栈用于存储线程的局部变量和方法调用信息。通过调整线程栈的大小,可以控制应用程序的并发性能和内存使用情况
  • -XX:MetaspaceSize=256m参数,您可以指定元空间的初始大小为256MB。这意味着在应用程序启动时,虚拟机会预分配256MB的内存用于存储类的元数据
  • -XX:MaxMetaspaceSize=:指定元空间的最大大小。元空间用于存储类的元数据信息。例如,-XX:MaxMetaspaceSize=256m表示将元空间的最大大小设置为256MB。适当设置元空间的大小可以避免类加载和元数据溢出的问题
  • -D=设置系统属性。例如,-Djava.library.path=/path/to/libs设置java.library.path系统属性为/path/to/libs。您可以使用这个参数来配置应用程序的一些属性,例如文件路径、日志级别等。
  • -verbose:class:打印类加载信息。使用这个参数可以了解应用程序在运行过程中加载的类的详细信息,包括类的名称、来源等。
  • -verbose:gc打印垃圾回收信息。通过使用这个参数,您可以了解应用程序的垃圾回收情况,包括垃圾回收器的使用情况、回收的对象数量等。
  • -Dfile.encoding=:设置默认的文件编码。例如,-Dfile.encoding=UTF-8表示使用UTF-8编码来读取和写入文件。正确设置文件编码可以确保应用程序能够正确处理不同字符集的文本数据

以上是一些常用的java -jar命令的参数,通过灵活运用这些参数,您可以对应用程序的性能、内存使用和系统属性进行优化和配置。

4.1、示例使用

示例1: 前台启动

java -jar -Xms4096m -Xmx4096m -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m /opt/myapp/myapp.jar

在上述示例中,我们同时使用了多个参数。-Xms4096m设置初始堆内存为4096MB,-Xmx4096m设置最大堆内存为4096MB,-XX:MetaspaceSize=256m 将元空间的初始大小设置为256MB,-XX:MaxMetaspaceSize=256m 将元空间的最大大小设置为256MB,最后,通过-jar选项指定要运行的JAR文件为myapp.jar。

示例2: 后台启动,并输出日志到nohub.out

nohup /usr/local/java/jdk1.8.0_333/bin/java -jar -Xms8192m -Xmx8192m -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m -XX:+UseConcMarkSweepGC /home/myapp/myapp.jar > nohup.out 2>&1 &

4.2、启动脚本

一般情况了,我们会在jar包的同级目录下创建一个start.sh的启动脚本来启动我们的服务 示例1:启动脚本

#!/bin/sh
nohup /usr/local/java/jdk1.8.0_102/bin/java -jar -Xms4096m -Xmx4096m -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m   /home/myapp/myapp.jar  > nohup.out 2>&1 &

示例2:通用脚本

#!/bin/bash
# ##################################################################
# ### Service start script
# ##################################################################

# 方便查看日志,参数为 -f
PRG="$0"
P1=$1
#PRGDIR=`dirname "$PRG"`
PRGDIR=`pwd`

# ### 启动成功提示!
function success () {
    echo "#####"
    echo "####################### Start Service End! #######################"
    echo ""
    echo -e "                    \033[32;1;5m [ START SUCCESSFULLY! ]\033[0m"
    echo ""
}

# ### 启动失败提示警告!
function failed () {
    echo "#####"
    echo "####################### Start Service End! #######################"
    echo ""
    echo -e "                   \033[37;41;1;5m [ FAILED! FAILED! FAILED! ]\033[0m"
    echo -e "       \033[37;41;1;5m [ $1 ]\033[0m"
    echo ""
}

echo "####################### Start Service ############################"
echo "#####"
echo "##### Current Working Path: $PWD"

# ### Script running flag!
STATUS="OK!"

JAVA_VERSION=`java -version 2>&1 |awk 'NR==1{ gsub(/"/,""); print $3 }'`
echo "##### Java Version : $JAVA_VERSION"

# ### 判断jdk版本是否是1.8
JAVA_VERSION_P="1.8"
JAVA_PATH=""
if [[ $JAVA_VERSION =~ $JAVA_VERSION_P ]]
then
    echo "##### The JDK is OK!"
    JAVA_PATH=`which java`
else
    echo "##### The JDK is not supported!"
fi

# ### 扫描/opt和/usr目录获取JAVA_PATH
reg='jdk1.8.0_[0-9]{1,3}/bin/java'
if [ "$JAVA_PATH" = "" ]; then
    echo "##### Find JDK directory!"
    echo "##### '/opt' And '/usr' directory will be scanned."
    echo "##### Start scan '/opt' directory ... ..."
    JAVA_PATH_DIR=$(find /opt -name java 2>&1)
    for i in $JAVA_PATH_DIR
    do
        if [[ $i =~ $reg ]]; then
            echo "##### JDK_PATH : $i"
            echo "##### The JDK_PATH is OK!"
            JAVA_PATH=$i
        fi
    done
fi

if [ "$JAVA_PATH" = "" ]; then
    echo "##### '/opt' directory Not found the JDK!"
    echo "##### Start scan '/usr' directory ... ..."
    JAVA_PATH_DIR=$(find /usr -name java 2>&1)
    for i in $JAVA_PATH_DIR
    do
        if [[ $i =~ $reg ]]; then
            echo "##### JDK_PATH : $i"
            echo "##### The JDK_PATH is OK!"
            JAVA_PATH=$i
        fi
    done
fi
if [ "$JAVA_PATH" = "" ]; then
    echo "##### '/usr' directory Not found the JDK!"
    msg="The JDK Not found, Please configure the JDK!"
    echo "##### $msg"
    failed "$msg"
    exit
fi

# ### 获取jar文件,若多个jar文件,默认选择使用最新文件
echo "##### Get running jar file, if more than jar file, the default option is to use the latest file."
JarFileName=$(ls -lt $PRGDIR/*.jar 2>&1|awk '/^-/ {print $NF}'|sed -n '1p')
if [ -z "$JarFileName" ]; then
    msg="The jar file is not exist! Please confirm before implementation."
    echo "##### $msg"
    failed "$msg"
    exit
fi

echo "##### Currently Running JarFileName: $JarFileName"

# ### 设置JVM参数
CATALINA_OPTS="-Xms8192m -Xmx8192m -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m -XX:+UseConcMarkSweepGC"
RUN_COM="nohup $JAVA_PATH -jar $CATALINA_OPTS $JarFileName 2>&1"
echo "##### Run the command : $RUN_COM"
#nohup $JAVA_PATH -jar $CATALINA_OPTS $JarFileName > nohup.out 2>&1 &
setsid $JAVA_PATH -jar $CATALINA_OPTS $JarFileName > nohup.out 2>&1 &
# ### 将jar包启动对应的pid写入文件中,为停止时提供pidi
# echo $! > run.pid

if [ $? -eq 0 ]; then
    success
    if [  "$P1" == "-f" ]; then
        echo "#################### tail -f nohup.out #########################"
        tail -f nohup.out
    fi
else
    failed "$msg"
fi

总结

本文介绍了java -jar命令的常用参数、使用方法及其启动脚本,帮助您更好地掌握Java可执行JAR文件的运行技巧。通过合理配置这些参数,您可以优化应用程序的性能、内存使用和系统属性,提升应用程序的稳定性和效率。

在实际应用中,您可以根据具体的需求和环境进行参数的调整和配置。了解这些参数的功能和用法,对于开发和部署Java应用程序是非常有帮助的。

chatgpt中的详细说明

java -jar 命令用于运行可执行的 JAR 文件(Java 应用程序归档文件)。以下是 java -jar 命令的基本语法和常用参数的详细说明:

基本语法

java [options] -jar <jar-file> [args...]
  • options:Java 虚拟机(JVM)的启动参数,用于配置 JVM 的运行环境。
  • <jar-file>:要执行的 JAR 文件的路径。
  • [args...]:传递给主类的命令行参数

常用参数说明

JVM 相关参数

这些参数是java 命令的通用选项,与 JAR 文件无关。

  1. -Xmx<size> 设置 JVM 最大堆内存大小。 示例:-Xmx512m 表示将最大堆内存限制为 512 MB。

  2. -Xms<size> 设置 JVM 初始堆内存大小。 示例:-Xms256m 表示初始堆内存为 256 MB。

  3. -XX:+UseG1GC 使用 G1 垃圾回收器,提高垃圾回收效率。

  4. -D<name>=<value> 设置系统属性。 示例:-Denv=prod 表示设置系统属性 env 的值为 prod

  5. -XX:MaxPermSize=<size> (JDK 8 之前) 设置永久代的最大大小。 示例:-XX:MaxPermSize=128m。

  6. -XX:+PrintGCDetails 打印垃圾回收详细信息。


JAR 文件相关参数

  1. -cp 或 -classpath 用于指定依赖类路径(在 -jar 模式下不可用)。

  2. -jar 表示运行 JAR 文件。它会忽略 -cp 或 -classpath 参数,并从 JAR 文件中读取主类信息。


应用程序参数

这些参数是运行时传递给 Java 程序的。例如:

JAR 文件中主类的 main 方法可以接收这些参数。

public static void main(String[] args) {
    for (String arg : args) {
        System.out.println(arg);
    }
}

如果执行命令:

java -jar myapp.jar arg1 arg2

输出为:

arg1
arg2

示例用法

  1. 简单运行 JAR 文件
java -jar myapp.jar
  1. 设置 JVM 堆大小
java -Xms256m -Xmx512m -jar myapp.jar
  1. 设置系统属性
java -Dconfig.file=app.properties -jar myapp.jar
  1. 传递命令行参数
java -jar myapp.jar --port=8080 --env=production
  1. 调试模式运行
java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 -jar myapp.jar

注意事项

必须定义主类:META-INF/MANIFEST.MF 文件中必须包含 Main-Class 属性,例如:

Main-Class: com.example.Main

类路径:-jar 选项会忽略 -classpath,JAR 文件内部需包含所有依赖(或使用工具如 spring-boot-maven-plugin 构建 fat JAR)。