You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 08:30:05