如何在Ubuntu上运行Jar包?

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 【7月更文挑战第9天】

Java,一种广泛使用的面向对象编程语言,以其“编写一次,到处运行”的理念著称,是跨平台应用程序开发的首选。其核心优势在于Java虚拟机(JVM),它使得编写的Java代码能够在任何安装了JVM的设备上运行,无需重新编译。Ubuntu作为Linux发行版中的佼佼者,凭借其开源、稳定、易用的特性,成为了众多开发者部署Java应用的优选平台。

Jar(Java Archive)文件是一种归档文件格式,用于聚合多个Java类文件、相关的元数据和资源(如图像和配置文件)到单一文件中。Jar包不仅是发布Java应用程序的标准方式,也是库分发的常见形式。它简化了软件分发,便于版本控制,且通过内置的Manifest文件,能够指定主类(即应用程序入口点),从而直接通过Java命令行执行。

要在Ubuntu上运行Java程序,首要步骤是安装Java Development Kit (JDK)。以下是两种常见的安装方式:

对于大多数开发者而言,OpenJDK是性价比极高的选择,它完全开源且与Oracle JDK高度兼容。可以通过以下命令安装最新版本的OpenJDK:

sudo apt update
sudo apt install openjdk-17-jdk

安装完成后,可以使用java -versionjavac -version来验证安装是否成功。

尽管OpenJDK已经足够满足大多数需求,但某些特定场景可能需要Oracle JDK提供的额外功能。此时,可以从Oracle官网下载对应版本的JDK安装包,解压后手动配置环境变量。

Classpath是Java应用程序查找类和包的位置路径。正确设置Classpath对于解决“类找不到”错误至关重要。在命令行运行Java程序时,可以使用-cp-classpath选项指定。

Manifest文件位于Jar包的META-INF目录下,其中最重要的是Main-Class属性,它指明了应用程序的入口点。使用jar工具创建包含Manifest的可执行Jar包,示例如下:

  1. 编译源代码:
    javac -sourcepath src -d bin src/com/example/Main.java
    
  2. 创建包含Manifest的Jar包:
    jar cvfm MyApplication.jar manifest.txt -C bin .
    
    其中,manifest.txt内容应至少包含:
    Main-Class: com.example.Main
    

在Ubuntu上运行Jar包的基础步骤

直接运行已有的Jar包

一旦你的Java程序被打包成Jar文件,并且Manifest文件中正确设置了Main-Class属性,就可以在Ubuntu上直接运行这个Jar包了。这是最基本的步骤,适用于大多数简单应用。

  1. 检查Java环境:首先确保Java已正确安装并且在PATH中。可以在终端输入java -version来验证。

  2. 运行Jar包:使用java -jar命令,后面跟上你的Jar文件路径。例如,如果你的Jar文件名为MyApplication.jar,且位于当前目录下,只需输入:

    java -jar MyApplication.jar
    

    此命令告诉Java虚拟机从指定的Jar文件中加载主类,并执行main方法。

处理依赖问题

在实际开发中,Java应用往往依赖于外部库。这些依赖需要在运行时被正确地加载。有几种方法可以管理这些依赖:

使用Classpath参数

如果你的应用依赖于不在Jar文件内的其他库,可以在运行时通过-cp-classpath参数指定依赖的路径。例如:

java -cp lib/library.jar -jar MyApplication.jar

这告诉Java在执行前先将library.jar加入到类路径中。

使用构建工具(Maven或Gradle)

对于更复杂的项目,推荐使用构建工具如Maven或Gradle来管理依赖。这些工具可以自动下载所需库,并在构建过程中生成包含所有依赖的“Fat Jar”(也称作可执行Jar或Uber Jar)。

  • Maven:使用maven-assembly-plugin或maven-shade-plugin插件。
  • Gradle:使用shadow插件。

以Maven为例,首先在pom.xml中添加maven-shade-plugin配置:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>3.2.4</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <transformers>
                            <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                <mainClass>com.example.Main</mainClass>
                            </transformer>
                        </transformers>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

然后运行mvn clean package,Maven会生成一个包含所有依赖的可执行Jar。

配置环境变量

为了让Java命令在任何目录下都能被识别,通常需要设置JAVA_HOME和PATH环境变量。如果你使用的是OpenJDK,可以通过编辑~/.bashrc~/.profile文件来添加这些变量:

# 设置JAVA_HOME
export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
# 将Java的bin目录加入PATH
export PATH=$JAVA_HOME/bin:$PATH

保存更改后,执行source ~/.bashrcsource ~/.profile使修改生效。

高级操作与实践技巧

后台运行Java应用程序

在生产环境中,通常需要将Java应用程序作为守护进程在后台运行,以便即使用户注销系统后也能持续工作。以下是一些实现这一目标的方法:

  1. 使用screen或tmux:这两个工具允许你在会话中断后恢复。启动一个新的screen或tmux会话,然后在其中运行Java应用。
  • 使用screen:
screen -S myapp
java -jar MyApplication.jar
Ctrl + A, D  # 分离screen会话
  • 使用tmux:
tmux new -s myapp
java -jar MyApplication.jar
Ctrl + B, D  # 分离tmux会话
  1. nohup命令:使用nohup可以让程序忽略挂断信号(HUP),从而在终端关闭后继续运行。
nohup java -jar MyApplication.jar > app.log 2>&1 &
  1. Systemd服务:对于Ubuntu系统,创建一个Systemd服务单元文件是管理后台服务的标准方式。

创建/etc/systemd/system/myapp.service文件,内容如下:

[Unit]
Description=My Java Application
After=network.target

[Service]
User=your_username
ExecStart=/usr/bin/java -jar /path/to/MyApplication.jar
SuccessExitStatus=143
Restart=always

[Install]
WantedBy=multi-user.target

然后使用以下命令管理服务:

sudo systemctl start myapp
sudo systemctl enable myapp
sudo systemctl status myapp

日志管理

良好的日志记录是维护和调试应用程序的关键。Java应用可以通过以下方式管理日志:

  • 使用Log4j、logback或java.util.logging:这些是Java中常用的日志框架。在应用代码或配置文件中设置日志级别、输出目标(控制台、文件等)和格式化。

  • 配置日志输出:例如,在log4j.properties或logback.xml中指定日志文件路径和滚动策略,以避免日志文件无限增长。

性能监控与调优

  • JVisualVM:这是一个强大的可视化工具,用于监控Java应用程序的CPU、内存使用情况,分析堆和线程dump等。

  • JMX(Java Management Extensions):通过JMX,可以在运行时监控和管理Java应用的各种方面,如内存池、垃圾回收行为等。

  • GC日志分析:调整Java虚拟机的垃圾收集器参数,如使用-verbose:gc-Xloggc:gc.log来记录GC活动,并使用工具(如GCViewer)分析日志,优化内存管理和减少停顿时间。

  • 性能剖析:使用Java Mission Control (JMC) 或 YourKit等工具进行性能剖析,定位瓶颈并进行调优。

安全考虑

  • 权限管理:确保运行Java应用的用户具有最小必要的权限,避免以root身份运行非必需的服务。

  • 网络安全性:如果应用暴露了网络接口,确保使用安全协议(如HTTPS),并限制访问权限。

  • 依赖安全:定期检查项目依赖是否有已知的安全漏洞,使用OWASP Dependency-Check等工具进行扫描。

解决常见问题与故障排查

在Ubuntu上运行Java Jar包的过程中,可能会遇到各种预料之外的问题。

类找不到错误(ClassNotFoundException或NoClassDefFoundError)

  • 原因分析:这通常意味着Java虚拟机无法找到某个类的定义。可能是因为类路径(Classpath)设置错误,或者依赖的库未被正确包含。

  • 解决策略

    • 检查Manifest文件中的Class-Path属性是否正确指向了所有依赖的JAR。
    • 如果手动指定Classpath,确保所有必要的路径都被包括进来,使用 -cp-classpath 参数。
    • 对于使用构建工具(如Maven或Gradle)的项目,确认是否正确打包了所有依赖,尝试生成一个包含所有依赖的胖JAR(Fat JAR)。

内存溢出(OutOfMemoryError)

  • 原因分析:应用程序请求的内存超出了JVM分配的容量。

  • 解决策略

    • 调整JVM的堆内存大小,使用 -Xms 初始化堆大小,-Xmx 设置最大堆大小。例如:java -Xms512m -Xmx2g -jar MyApplication.jar
    • 分析内存泄漏,使用VisualVM或MAT(Memory Analyzer Tool)来检查内存使用情况,定位并修复泄露的源头。
    • 对于频繁的Full GC问题,考虑调整垃圾收集策略或使用G1垃圾收集器。

版本兼容性问题

  • 原因分析:不同的Java版本对某些API的支持可能有所不同,导致在高版本JDK编译的代码无法在低版本JVM上运行。

  • 解决策略

    • 确保开发和生产环境使用相同版本的JDK。
    • 如果必须跨版本部署,使用较低版本的JDK进行编译,或使用像Retrolambda这样的工具来向后兼容旧版本的Java。
    • 检查项目依赖,确保它们也与目标JDK版本兼容。

应用程序启动慢或响应迟缓

  • 原因分析:可能是启动时初始化太多资源,或者运行时有性能瓶颈。

  • 解决策略

    • 使用JProfiler或VisualVM等工具进行性能分析,识别瓶颈所在。
    • 优化代码逻辑,减少不必要的资源初始化,延迟加载非关键组件。
    • 调整JVM参数,比如增加年轻代大小,优化垃圾回收算法,减少GC压力。

网络连接问题

  • 原因分析:应用无法访问外部服务,可能是网络配置、防火墙限制或DNS解析问题。

  • 解决策略

    • 检查应用的网络权限,确保它有访问外网的权限。
    • 使用pingtraceroute命令测试网络连通性。
    • 检查应用的网络配置,确保使用正确的主机名或IP地址。
    • 查看系统防火墙规则,必要时开放相应端口。

持续集成与部署(CI/CD)实践

在现代软件开发流程中,持续集成(Continuous Integration, CI)和持续部署(Continuous Deployment, CD)对于提高Java应用的开发效率、保证代码质量以及快速交付至关重要。

1. 选择合适的CI/CD工具

  • Jenkins: 是最流行的开源CI/CD服务器之一,提供了丰富的插件生态系统,支持各种构建、测试和部署任务。
  • GitLab CI/CD: 如果项目托管在GitLab上,可以利用其内置的CI/CD管道功能,通过.gitlab-ci.yml配置文件管理构建和部署流程。
  • GitHub Actions: 为GitHub仓库提供强大的自动化工作流,通过简单的yaml文件配置即可实现从代码提交到部署的全过程。
  • Travis CICircleCI: 常用于开源项目,提供云原生的CI/CD服务,易于配置且与GitHub集成紧密。

2. 配置自动构建

  • 构建触发器: 设置每次代码推送(commit或merge request)后自动触发构建。
  • 构建脚本: 编写构建脚本(如Shell脚本或Gradle/Maven命令),完成编译、测试、打包等操作。确保构建过程自动化且可重复。
  • 依赖管理: 在CI环境中自动处理依赖下载,避免因本地缓存造成构建差异。

3. 集成测试

  • 单元测试: 自动运行单元测试套件,确保新提交的代码没有破坏现有功能。
  • 集成测试: 对应用程序与其他系统交互的部分进行测试,确保集成顺畅。
  • 代码覆盖率报告: 生成并查看测试覆盖率报告,作为代码质量的一个指标。

4. 验证与静态代码分析

  • 代码质量检查: 使用SonarQube、Checkstyle、PMD等工具进行静态代码分析,发现潜在的代码质量问题和不良编程习惯。
  • 安全性扫描: 使用OWASP Dependency-Check等工具检查依赖是否有已知的安全漏洞。

5. 自动部署

  • 环境准备: 确保各个部署环境(如开发、测试、生产)配置一致,可以使用基础设施即代码(IaC)工具如Terraform或Ansible进行管理。
  • 蓝绿部署/金丝雀发布: 实施零停机部署策略,减少服务中断风险。
  • 容器化部署: 利用Docker容器化应用,结合Kubernetes或Docker Compose进行部署管理,提高部署灵活性和可扩展性。
  • 自动化回滚策略: 部署失败时能快速自动回滚到上一个稳定版本。

6. 监控与日志

  • 应用性能监控: 使用Prometheus、Grafana或ELK Stack(Elasticsearch、Logstash、Kibana)监控应用性能和日志,及时发现并解决问题。
  • 健康检查: 实现应用健康检查端点,供CI/CD流程验证部署状态。

通过实施这些实践,可以显著提升Java应用的开发效率和部署质量,确保快速迭代的同时保持系统的稳定性和可靠性。

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
3月前
|
Java 应用服务中间件 Spring
为什么SpringBoot的 jar 可以直接运行?
SpringBoot的 jar 可以直接运行的原因
383 2
|
1月前
|
存储 数据可视化 Java
震惊!如何在linux下部署项目,部署/运行jar包 超详细保姆级教程!
如何在Linux系统下部署和运行Java项目jar包,包括传输文件到Linux、使用nohup命令运行jar包、查看端口状态、杀死进程和查看项目运行状态,以及如何解决“没有主清单属性”的错误。
429 1
震惊!如何在linux下部署项目,部署/运行jar包 超详细保姆级教程!
|
1月前
|
Java Windows
如何在windows上运行jar包/JAR文件 如何在cmd上运行 jar包 保姆级教程 超详细
本文提供了一个详细的教程,解释了如何在Windows操作系统的命令提示符(cmd)中运行JAR文件。
865 1
|
3月前
|
Java Maven 容器
Maven使用IDEA自带工具打包,同时将lib下的jar包打入,双击jar包可直接运行
使用IntelliJ IDEA的Artifacts功能,可以将项目依赖的第三方jar包打包进jar文件中,实现双击jar包即可直接运行。
Maven使用IDEA自带工具打包,同时将lib下的jar包打入,双击jar包可直接运行
|
2月前
|
Ubuntu NoSQL
ubuntu上安装某个程序的符号表和源码包
ubuntu上安装某个程序的符号表和源码包
|
2月前
|
Ubuntu
树莓派 —— 关闭安装软件包时ubuntu对内核版本等的检查
树莓派 —— 关闭安装软件包时ubuntu对内核版本等的检查
|
2月前
|
Ubuntu
使用dpkg在ubuntu上安装软件包遇到依赖包的问题
使用dpkg在ubuntu上安装软件包遇到依赖包的问题
|
3月前
|
Ubuntu Shell C++
在Ubuntu18.04上安装ros2的环境,ros2的常用命令:播放包、录制包等
在Ubuntu18.04上安装ros2的环境,ros2的常用命令:播放包、录制包等
176 1
|
3月前
|
Ubuntu 网络协议 Shell
ubuntu下docker及打deb包
ubuntu下docker及打deb包
40 2
|
3月前
|
SQL 前端开发 Java
在IDEA中使用Maven将SpringBoot项目打成jar包、同时运行打成的jar包(前后端项目分离)
这篇文章介绍了如何在IntelliJ IDEA中使用Maven将Spring Boot项目打包成可运行的jar包,并提供了运行jar包的方法。同时,还讨论了如何解决jar包冲突问题,并提供了在IDEA中同时启动Vue前端项目和Spring Boot后端项目的步骤。
在IDEA中使用Maven将SpringBoot项目打成jar包、同时运行打成的jar包(前后端项目分离)