背景介绍:因langchain4j最新版本(>=0.36.0)(Min JDK version has been upgraded to 17)需JDK17起,故直接使用Amazon Corretto JDK 21作为基础镜像。
在使用 JDK21 进行开发或运行相关应用时,有时会遭遇令人困扰的问题。今天运行 java -jar xxx.jar时出现 “Error: An unexpected error occurred while trying to open file xxx.jar” 这样的错误提示,给开发进程带来阻碍。接下来我们将逐步重现该过程以及如何绕过该问题。
容器环境
宿主机:CentOS Linux release 7.6.1810 (Core)
Docker版本:
containerd.io.x86_64 1.2.13-3.2.el7 @docker-ce-stable
docker-ce.x86_64 3:19.03.12-3.el7 @docker-ce-stable
docker-ce-cli.x86_64 1:19.03.12-3.el7 @docker-ce-stable
Docker-Compose:docker-compose version 1.26.2, build eefe0d31
镜像构建脚本
直接复制 corretto-docker-debain-21 的脚本
FROM debian:buster-slim
ARG version=21.0.5.11-1
# In addition to installing the Amazon corretto, we also install
# fontconfig. The folks who manage the docker hub's
# official image library have found that font management
# is a common usecase, and painpoint, and have
# recommended that Java images include font support.
#
# See:
# https://github.com/docker-library/official-images/blob/master/test/tests/java-uimanager-font/container.java
RUN set -eux \
&& apt-get update \
&& apt-get install -y --no-install-recommends \
curl ca-certificates gnupg software-properties-common fontconfig java-common \
&& curl -fL https://apt.corretto.aws/corretto.key | apt-key add - \
&& add-apt-repository 'deb https://apt.corretto.aws stable main' \
&& mkdir -p /usr/share/man/man1 || true \
&& apt-get update \
&& apt-get install -y java-21-amazon-corretto-jdk=1:$version \
&& apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \
curl gnupg software-properties-common
ENV LANG=C.UTF-8
ENV JAVA_HOME=/usr/lib/jvm/java-21-amazon-corretto
测试代码
代码结构
├─src
│ ├─main
│ │ ├─java
│ │ │ └─com
│ │ │ └─sample
│ │ └─resources
│ └─test
└─java
pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sample</groupId>
<artifactId>Sample</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<jdk-version>21</jdk-version>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<maven-source-plugin>3.2.1</maven-source-plugin>
<maven-compiler-plugin-version>3.11.0</maven-compiler-plugin-version>
<maven-surefire-plugin-version>3.1.0</maven-surefire-plugin-version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.0</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>${maven-source-plugin}</version>
<executions>
<execution>
<id>attach-sources</id>
<phase>install</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${jdk-version}</source>
<target>${jdk-version}</target>
<parameters>true</parameters>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin-version}</version>
<configuration>
<forkCount>1</forkCount>
<reuseForks>true</reuseForks>
<argLine>-Dfile.encoding=UTF-8</argLine>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>3.1.6</version>
<configuration>
<mainClass>com.sample.Application</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<classifier>exec</classifier>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Application
package com.sample;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
logback.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<property name="log.pattern"
value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{traceId}] [%thread] %-5level %logger{20} - [%method,%line] - %msg%n"/>
<logger name="org.springframework.web" level="INFO"/>
<logger name="org.springframework.jdbc" level="INFO"/>
<logger name="com.sample" level="INFO"/>
<appender name="consoleAppender" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
<level>debug</level>
</filter>
</appender>
<springProfile name="dev">
<root level="INFO">
<appender-ref ref="consoleAppender"/>
</root>
</springProfile>
<springProfile name="test">
<property name="log.path" value="/data/logs"/>
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/log4i.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/log4i.log.%d{yyyy-MM-dd}</fileNamePattern>
<maxHistory>180</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>DEBUG</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>ACCEPT</onMismatch>
</filter>
</appender>
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/log4e.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/log4e.log.%d{yyyy-MM-dd}</fileNamePattern>
<maxHistory>365</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<root level="info">
<appender-ref ref="file_info"/>
<appender-ref ref="file_error"/>
</root>
</springProfile>
<springProfile name="prod">
<property name="log.path" value="/data/logs"/>
<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/log4i.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/log4i.log.%d{yyyy-MM-dd}</fileNamePattern>
<maxHistory>180</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${log.path}/log4e.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/log4e.log.%d{yyyy-MM-dd}</fileNamePattern>
<maxHistory>180</maxHistory>
</rollingPolicy>
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<root level="info">
<appender-ref ref="file_info"/>
<appender-ref ref="file_error"/>
</root>
</springProfile>
</configuration>
构建工程
mvn clean package
容器内运行工程
什么问题引起?
暂时未知,只好换旧版的JDK21(21.0.0.35.1)试试
安装完成后验证版本
root@e3bd319b01b7:/home# java -version
openjdk version "21" 2023-09-19 LTS
OpenJDK Runtime Environment Corretto-21.0.0.35.1 (build 21+35-LTS)
OpenJDK 64-Bit Server VM Corretto-21.0.0.35.1 (build 21+35-LTS, mixed mode, sharing)
运行工程
至此绕过 Error: An unexpected error occurred while trying to open file Sample-1.0-SNAPSHOT-exec.jar 的问题。
最后,若你知道如何解决该问题,请留言。