Quarkus 3使用Google ZXing生成二维码原生构建报错求助
解决Quarkus 3原生构建二维码生成的UnsatisfiedLinkError问题
问题概述
开发Quarkus 3应用生成二维码时,JVM模式运行正常,但原生打包后启动报错,提示UnsatisfiedLinkError: no awt in java.library.path。原因是Zxing的javase依赖依赖AWT组件,而使用的ubi-minimal极简镜像缺少AWT所需的系统库支持。
错误信息
Caused by: java.lang.UnsatisfiedLinkError: no awt in java.library.path at org.graalvm.nativeimage.builder/com.oracle.svm.core.jdk.NativeLibrarySupport.loadLibraryRelative(NativeLibrarySupport.java:136) at java.base@17.0.8/java.lang.ClassLoader.loadLibrary(ClassLoader.java:50)
当前配置
pom.xml依赖
<dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-awt</artifactId> </dependency> <dependency> <groupId>com.google.zxing</groupId> <artifactId>core</artifactId> <version>3.5.2</version> </dependency> <dependency> <groupId>com.google.zxing</groupId> <artifactId>javase</artifactId> <version>3.5.2</version> </dependency>
二维码生成代码
public class QRCodeGenerator { public static byte[] getQRCodeBytes(String text, int width, int height) throws WriterException, IOException { String imageFormat = "png"; // could be "gif", "tiff", "jpeg" QRCodeWriter qrCodeWriter = new QRCodeWriter(); BitMatrix bitMatrix = qrCodeWriter. encode(text, BarcodeFormat.QR_CODE, width, height); ByteArrayOutputStream pngOutputStream = new ByteArrayOutputStream(); MatrixToImageWriter.writeToStream(bitMatrix, imageFormat, pngOutputStream); return pngOutputStream.toByteArray(); } public static String getQRCodeBase64(String text, int width, int height) throws WriterException, IOException { return encodeBase64String(getQRCodeBytes(text, width, height)); } private static String encodeBase64String(byte[] binaryData) { return Base64.getEncoder().encodeToString(binaryData); } }
Dockerfile
FROM registry.access.redhat.com/ubi8/ubi-minimal:8.8 WORKDIR /work/ COPY ./build_files/*-runner /work/application EXPOSE 8080 ENTRYPOINT ["./application", "-Dquarkus.http.host=0.0.0.0"]
解决方案
方案1:修复AWT依赖问题
1. 更换基础镜像
ubi-minimal是极简镜像,缺少AWT系统库,替换为包含AWT支持的镜像:
# 使用Quarkus官方原生镜像 FROM quay.io/quarkus/quarkus-micro-image:2.0 WORKDIR /work/ COPY ./build_files/*-runner /work/application EXPOSE 8080 ENTRYPOINT ["./application", "-Dquarkus.http.host=0.0.0.0"]
或使用ubi-full镜像:
FROM registry.access.redhat.com/ubi8/ubi:8.8 WORKDIR /work/ COPY ./build_files/*-runner /work/application EXPOSE 8080 ENTRYPOINT ["./application", "-Dquarkus.http.host=0.0.0.0"]
2. 添加GraalVM原生配置
在src/main/resources/META-INF/native-image目录下创建native-image.properties,添加AWT初始化配置:
Args = --enable-all-security-services --initialize-at-build-time=java.awt,java.awt.image
方案2:使用无AWT依赖的二维码生成实现
移除对AWT的依赖,改用纯Java逻辑生成二维码,避免原生构建的兼容性问题。
步骤1:调整依赖
移除Zxing的javase依赖,只保留core:
<dependency> <groupId>io.quarkus</groupId> <artifactId>quarkus-awt</artifactId> <scope>provided</scope> <!-- 不再需要可直接删除 --> </dependency> <dependency> <groupId>com.google.zxing</groupId> <artifactId>core</artifactId> <version>3.5.2</version> </dependency>
步骤2:修改生成代码
自定义BitMatrix转PNG的逻辑,无需AWT:
import com.google.zxing.BarcodeFormat; import com.google.zxing.WriterException; import com.google.zxing.common.BitMatrix; import com.google.zxing.qrcode.QRCodeWriter; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Base64; public class QRCodeGenerator { private static final int ON_COLOR = 0xFF000000; // 黑色 private static final int OFF_COLOR = 0xFFFFFFFF; // 白色 public static byte[] getQRCodeBytes(String text, int width, int height) throws WriterException, IOException { QRCodeWriter qrCodeWriter = new QRCodeWriter(); BitMatrix bitMatrix = qrCodeWriter.encode(text, BarcodeFormat.QR_CODE, width, height); BufferedImage image = convertBitMatrixToImage(bitMatrix); ByteArrayOutputStream pngOutputStream = new ByteArrayOutputStream(); ImageIO.write(image, "png", pngOutputStream); return pngOutputStream.toByteArray(); } public static String getQRCodeBase64(String text, int width, int height) throws WriterException, IOException { return Base64.getEncoder().encodeToString(getQRCodeBytes(text, width, height)); } private static BufferedImage convertBitMatrixToImage(BitMatrix matrix) { int width = matrix.getWidth(); int height = matrix.getHeight(); BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { image.setRGB(x, y, matrix.get(x, y) ? ON_COLOR : OFF_COLOR); } } return image; } }
步骤3:添加ImageIO原生配置
在native-image.properties中添加ImageIO的初始化规则:
Args = --initialize-at-build-time=javax.imageio,javax.imageio.stream
内容的提问来源于stack exchange,提问作者Fyruz
相关产品推荐
相关产品推荐

