oracle / graal

GraalVM compiles Java applications into native executables that start instantly, scale fast, and use fewer compute resources 🚀
https://www.graalvm.org
Other
20.39k stars 1.64k forks source link

No awt in java.library.path #7849

Closed PavelBortnovskyi closed 10 months ago

PavelBortnovskyi commented 11 months ago

Hi. I am have such JAVA code in my pet project that I am running in GraalVM Native Image:

`import ij.ImagePlus; import ij.process.ColorProcessor; import ij.process.ImageProcessor; import org.springframework.stereotype.Component; import org.telegram.telegrambots.meta.api.objects.InputFile;

import javax.imageio.ImageIO; import java.awt.Color; import java.awt.Font; import java.awt.FontMetrics; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream;

@Component public class ImageFactory {

public InputFile createImageWithText(String text, int fontSize, int backgroundNumber) throws IOException {

    String backgroundResource = String.format("/Images/background%d.jpg", backgroundNumber + 1);

    try (InputStream resourceStream = getClass().getResourceAsStream(backgroundResource);
         ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {

        BufferedImage bufferedImage = ImageIO.read(resourceStream);
        ImagePlus image = new ImagePlus("Background", new ColorProcessor(bufferedImage));
        ImageProcessor ip = image.getProcessor();

        Font font = new Font(Font.MONOSPACED, Font.BOLD, fontSize);
        ip.setFont(font);
        ip.setColor(Color.WHITE);
        FontMetrics fontMetrics = ip.getFontMetrics();
        int charWidth = fontMetrics.charWidth('A');

        String[] lines = text.split("\n");
        int x = 20;
        int y = ip.getFontMetrics().getHeight();
        for (String line : lines) {
            if (line.contains("(")) {
                String[] subLines = line.split("\\(");
                ip.drawString(subLines[0], x, y += ip.getFontMetrics().getHeight());
                if (subLines[1].contains("-")) ip.setColor(Color.RED);
                else {
                    ip.setColor(Color.GREEN);
                }
                ip.drawString("(" + subLines[1], x + charWidth * subLines[0].length(), y);
                ip.setColor(Color.WHITE);
            } else ip.drawString(line, 30, y += ip.getFontMetrics().getHeight() + 20);
        }
        ImageIO.write(ip.getBufferedImage(), "jpg", outputStream);
        return new InputFile(new ByteArrayInputStream(outputStream.toByteArray()), "prices.jpg");
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}

}`

and it produces the error:

Exception in thread "crypto_currencies_pet_bot Telegram Executor" java.lang.UnsatisfiedLinkError: No awt in java.library.path 2023-11-18 21:51:59 at org.graalvm.nativeimage.builder/com.oracle.svm.core.jdk.NativeLibrarySupport.loadLibraryRelative(NativeLibrarySupport.java:136) 2023-11-18 21:51:59 at java.base@21.0.1/java.lang.ClassLoader.loadLibrary(ClassLoader.java:106) 2023-11-18 21:51:59 at java.base@21.0.1/java.lang.Runtime.loadLibrary0(Runtime.java:916) 2023-11-18 21:51:59 at java.base@21.0.1/java.lang.System.loadLibrary(System.java:2059) 2023-11-18 21:51:59 at java.desktop@21.0.1/java.awt.Toolkit$2.run(Toolkit.java:1384) 2023-11-18 21:51:59 at java.desktop@21.0.1/java.awt.Toolkit$2.run(Toolkit.java:1382) 2023-11-18 21:51:59 at java.base@21.0.1/java.security.AccessController.executePrivileged(AccessController.java:129) 2023-11-18 21:51:59 at java.base@21.0.1/java.security.AccessController.doPrivileged(AccessController.java:319) 2023-11-18 21:51:59 at java.desktop@21.0.1/java.awt.Toolkit.loadLibraries(Toolkit.java:1381) 2023-11-18 21:51:59 at java.desktop@21.0.1/java.awt.Toolkit.initStatic(Toolkit.java:1419) 2023-11-18 21:51:59 at java.desktop@21.0.1/java.awt.Toolkit.(Toolkit.java:1393) 2023-11-18 21:51:59 at java.base@21.0.1/java.lang.Class.ensureInitialized(DynamicHub.java:595) 2023-11-18 21:51:59 at java.desktop@21.0.1/sun.awt.AppContext$2.run(AppContext.java:273) 2023-11-18 21:51:59 at java.desktop@21.0.1/sun.awt.AppContext$2.run(AppContext.java:262) 2023-11-18 21:51:59 at java.base@21.0.1/java.security.AccessController.executePrivileged(AccessController.java:129) 2023-11-18 21:51:59 at java.base@21.0.1/java.security.AccessController.doPrivileged(AccessController.java:319) 2023-11-18 21:51:59 at java.desktop@21.0.1/sun.awt.AppContext.initMainAppContext(AppContext.java:262) 2023-11-18 21:51:59 at java.desktop@21.0.1/sun.awt.AppContext$3.run(AppContext.java:315) 2023-11-18 21:51:59 at java.desktop@21.0.1/sun.awt.AppContext$3.run(AppContext.java:298) 2023-11-18 21:51:59 at java.base@21.0.1/java.security.AccessController.executePrivileged(AccessController.java:129) 2023-11-18 21:51:59 at java.base@21.0.1/java.security.AccessController.doPrivileged(AccessController.java:319) 2023-11-18 21:51:59 at java.desktop@21.0.1/sun.awt.AppContext.getAppContext(AppContext.java:297) 2023-11-18 21:51:59 at java.desktop@21.0.1/javax.imageio.spi.IIORegistry.getDefaultInstance(IIORegistry.java:123) 2023-11-18 21:51:59 at java.desktop@21.0.1/javax.imageio.ImageIO.(ImageIO.java:64) 2023-11-18 21:51:59 at com.neo.crypto_bot.service.ImageFactory.createImageWithText(ImageFactory.java:29) 2023-11-18 21:51:59 at com.neo.crypto_bot.command.FavoriteCommandHandler.execute(FavoriteCommandHandler.java:72) 2023-11-18 21:51:59 at org.telegram.telegrambots.extensions.bots.commandbot.commands.BotCommand.processMessage(BotCommand.java:78) 2023-11-18 21:51:59 at org.telegram.telegrambots.extensions.bots.commandbot.commands.CommandRegistry.executeCommand(CommandRegistry.java:109) 2023-11-18 21:51:59 at org.telegram.telegrambots.extensions.bots.commandbot.TelegramLongPollingCommandBot.onUpdateReceived(TelegramLongPollingCommandBot.java:104) 2023-11-18 21:51:59 at java.base@21.0.1/java.util.ArrayList.forEach(ArrayList.java:1596) 2023-11-18 21:51:59 at org.telegram.telegrambots.meta.generics.LongPollingBot.onUpdatesReceived(LongPollingBot.java:27) 2023-11-18 21:51:59 at org.telegram.telegrambots.updatesreceivers.DefaultBotSession$HandlerThread.run(DefaultBotSession.java:312) 2023-11-18 21:51:59 at org.graalvm.nativeimage.builder/com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine(PlatformThreads.java:832) 2023-11-18 21:51:59 at org.graalvm.nativeimage.builder/com.oracle.svm.core.posix.thread.PosixPlatformThreads.pthreadStartRoutine(PosixPlatformThreads.java:211)

I am using container-registry.oracle.com/graalvm/native-image:21.0.1-ol8, but tried lot of options with same result Can be reproduced in this way: 1) docker pull pavelbortnovskyi/crypto-bot-awt-error:latest 2) run /get_all_favorite_pairs in https://t.me/crypto_currencies_pet_bot

elkorchi commented 11 months ago

Hello, can you add more context to the issue :

PavelBortnovskyi commented 11 months ago

Hello, can you add more context to the issue :

* Can you please share your DockerFile ?

* Can you please share the set of commands that your are using to get this error ? And the set of external dependencies you are using ?

Dependencies from pom.xml:

 <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.telegram</groupId>
            <artifactId>telegrambots</artifactId>
            <version>6.7.0</version>
        </dependency>
        <dependency>
            <groupId>org.telegram</groupId>
            <artifactId>telegrambotsextensions</artifactId>
            <version>6.7.0</version>
        </dependency>
        <dependency>
            <groupId>org.telegram</groupId>
            <artifactId>telegrambots-spring-boot-starter</artifactId>
            <version>6.7.0</version>
        </dependency>
        <dependency>
            <groupId>com.vdurmont</groupId>
            <artifactId>emoji-java</artifactId>
            <version>5.1.1</version>
        </dependency>
        <dependency>
            <groupId>net.imagej</groupId>
            <artifactId>ij</artifactId>
            <version>1.54c</version>
        </dependency>
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>4.11.0</version>
        </dependency>
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>42.5.4</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-validation</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>exec-maven-plugin</artifactId>
            <version>3.1.0</version>
        </dependency>
    </dependencies>
**Docker file:**
# Using Oracle GraalVM for JDK 21
FROM container-registry.oracle.com/graalvm/native-image:21.0.1-ol8 AS builder

# Set the working directory to /home/app
WORKDIR /build

# Copy the source code into the image for building
COPY .. /build

# Build                                                 
RUN ./mvnw --no-transfer-progress native:compile -Pnative

# The deployment Image
FROM container-registry.oracle.com/os/oraclelinux:8-slim

# Set bot and Binance API configuration as environment variables
ENV SPRING_PROFILES_ACTIVE=deploy
ENV bot_name="crypto_currencies_pet_bot"
ENV bot_token="***************"
ENV binance_api_tickerPrice_url="https://api.binance.com/api/v3/ticker/price"
ENV binance_api_exchangeInfo_url="https://api.binance.com/api/v3/exchangeInfo"
ENV binance_api_avgPrice_url="https://api.binance.com/api/v3/avgPrice"
ENV binance_api_convertible_url="https://api.binance.com/sapi/v1/convert/exchangeInfo"
ENV elephant_db_password="**********************"
EXPOSE 8080

# Copy the native executable into the containers
COPY --from=builder /build/target/native-crypto-bot-image app

#Launch image
#For oraclelinux
ENTRYPOINT ["/app"]
elkorchi commented 10 months ago

Thank you,

First please use an updated docker image with the latest GraalVM : container-registry.oracle.com/graalvm/native-image:21-ol8

For the AWT error, I think you had a recommandation in the ouput of the native-image generation like :

Recommendations:
 AWT:  Use the tracing agent to collect metadata for AWT.

Which wasn't taken in consideration. To fix that you should run tracing agent to collect Metadata config https://www.graalvm.org/latest/reference-manual/native-image/metadata/AutomaticMetadataCollection/ with the following :

java -agentlib:native-image-agent=config-output-dir=conf MainClass

Then run the native-image generation with the new metadata configuration :

native-image -H:ConfigurationFileDirectories=conf MainClass

elkorchi commented 10 months ago

Closing this issue for inactivity. if these still relevant, please reopen. Thank you