Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GraalVM Native SocketDataPort ClassNotFoundException again #1021

Closed
Alfablos opened this issue Oct 21, 2023 · 9 comments
Closed

GraalVM Native SocketDataPort ClassNotFoundException again #1021

Alfablos opened this issue Oct 21, 2023 · 9 comments
Labels
defect Suspected defect such as a bug or regression

Comments

@Alfablos
Copy link

Observed behavior

Hello,
I'm trying to build a small program as a binary using GraalVM Native.
It compiles fine but when I run the executable the following exception is thrown:

Exception in thread "main" java.lang.IllegalArgumentException: java.lang.ClassNotFoundException: io.nats.client.impl.SocketDataPort
        at io.nats.client.Options$Builder.createInstanceOf(Options.java:875)
        at io.nats.client.Options.buildDataPort(Options.java:1733)
        at io.nats.client.impl.NatsConnection.tryToConnect(NatsConnection.java:424)
        at io.nats.client.impl.NatsConnection.connect(NatsConnection.java:207)
        at io.nats.client.impl.NatsImpl.createConnection(NatsImpl.java:29)
        at io.nats.client.Nats.createConnection(Nats.java:303)
        at io.nats.client.Nats.connect(Nats.java:155)
        at com.example.hyprtesseract.StorageInterface.<init>(StorageInterface.java:24)
        at com.example.hyprtesseract.HyprTesseract.main(HyprTesseract.java:24)
        at java.base@21/java.lang.invoke.LambdaForm$DMH/sa346b79c.invokeStaticInit(LambdaForm$DMH)
Caused by: java.lang.ClassNotFoundException: io.nats.client.impl.SocketDataPort
        at org.graalvm.nativeimage.builder/com.oracle.svm.core.hub.ClassForNameSupport.forName(ClassForNameSupport.java:122)
        at org.graalvm.nativeimage.builder/com.oracle.svm.core.hub.ClassForNameSupport.forName(ClassForNameSupport.java:86)
        at java.base@21/java.lang.Class.forName(DynamicHub.java:1346)
        at java.base@21/java.lang.Class.forName(DynamicHub.java:1309)
        at java.base@21/java.lang.Class.forName(DynamicHub.java:1302)
        at io.nats.client.Options$Builder.createInstanceOf(Options.java:871)
        ... 9 more
Oct 21, 2023 6:58:46 PM io.nats.client.impl.ErrorListenerLoggerImpl exceptionOccurred
SEVERE: exceptionOccurred, Exception: java.lang.IllegalArgumentException: java.lang.ClassNotFoundException: io.nats.client.impl.SocketDataPort

I've searched for similar issues and the only one I found is this one (116) from micronaut-nacts, Graalvm - Nats - Problems when running the application.
It appears that the solution was confirmed here.

This all dates back to 2020. I'm not using any particular framework, just vanilla Java for now and I'm unsure about how to have that class resolved.

Thank you

Expected behavior

Binary executable runs with no exceptions.

Server and client version

nats-server 2.10.3
jnats 2.17.1, 2.16.11
GraalVM (JDK) 17, 21
gradle 8.3

Host environment

EndeavourOS (Arch)

build.gradle.kts

java.sourceCompatibility = JavaVersion.VERSION_21

configurations {
    compileOnly {
        extendsFrom(configurations.annotationProcessor.get())
    }
}

graalvmNative {
    testSupport.set(false)
    binaries {
        named("main") {
            buildArgs.add("-H:+StaticExecutableWithDynamicLibC")
            javaLauncher.set(javaToolchains.launcherFor {
                languageVersion.set(JavaLanguageVersion.of(21))
                vendor.set(JvmVendorSpec.matching("GraalVM Community"))
            })

            debug.set(true)
        }
        all {
            resources.autodetect()
        }
    }
    toolchainDetection.set(true)
}


Steps to reproduce

Create an instance of "Connection" by connecting to a server and then run the task nativeRun in gradle (or nativeCompile and then run the executable).

@Alfablos Alfablos added the defect Suspected defect such as a bug or regression label Oct 21, 2023
@scottf
Copy link
Contributor

scottf commented Oct 23, 2023

We are aware that nats is not GraalVM friendly but as you said it's pretty plain vanilla, so it can't to too far, but needs a full analysis.

@scottf
Copy link
Contributor

scottf commented Oct 23, 2023

@Alfablos Can you try this snapshot: 2.17.1.GraalVM-remove-reflection-SNAPSHOT

Not sure how you get your dependencies. For gradle and maven, you can get instructions here:
https://github.com/nats-io/nats.java#using-gradle

If you need, I could get you the jar directly. There is also a branch in the repo: https://github.com/nats-io/nats.java/tree/GraalVM-remove-reflection

@scottf
Copy link
Contributor

scottf commented Oct 23, 2023

Also, there may be issues compiling directly with Java 17

@Alfablos
Copy link
Author

Thank you!
So, the error about the SocketDataPort is gone.

I have an exception related to Jackson trying to deserialize the message payload but I'm not sure this is something that needs to be addressed your side.
Basically Payload is a record defined as follows:

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

@JsonIgnoreProperties(ignoreUnknown = true)
public record Payload(String name, String bucket, String nuid, String mtime, long size, int chunks, String digest) {

    public int chunks() {
        return this.chunks;
    }
}

Deserialization fails with this error:

SEVERE: exceptionOccurred, Connection: 28, Exception: java.lang.RuntimeException: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.example.hyprtesseract.Payload`: cannot deserialize from Object value (no delegate- or property-based Creator): this appears to be a native image, in which case you may need to configure reflection for the class that is to be deserialized

I haven't tried using a conventional class though.

I always get this error regardless of the usage of GraalVM:
Oct 23, 2023 10:45:09 PM io.nats.client.impl.ErrorListenerLoggerImpl exceptionOccurred
But it doesn't impact functionality.

Java 17 + GraalVM: same jackson error with the SNAPSHOT version, ClassNotFoundException (SocketDataPort) with the stable one.
Java 17 no GraalVM: everything works.
Java 21 no GraalVM: everything works.

:)

@scottf
Copy link
Contributor

scottf commented Oct 23, 2023

The library does not use jackson so that is on your side. I saw that the GraalVM docs have specific notes about serialization, I would start there.

As far as the ErrorListenerLoggerImpl exceptionOccurred is there any more context around this?

@Alfablos
Copy link
Author

The library does not use jackson so that is on your side. I saw that the GraalVM docs have specific notes about serialization, I would start there.
I will, thanks!

As far as the ErrorListenerLoggerImpl exceptionOccurred is there any more context around this?
That particular error went away once I installed a proper logging facility (Slf4j + Logback).
Another error shows up when I download a file from a bucket:

Oct 23, 2023 11:34:37 PM io.nats.client.impl.ErrorListenerLoggerImpl flowControlProcessed
INFO: flowControlProcessed, Connection: 245, Subscription: 2098327494, Consumer Name: mqFMjLUafg, FlowControlSource:FLOW_CONTROL

But again, this is most likely on me. This little repo is a draft for testing some functionalities and I wasn't that careful about configuration. I mentioned It in case It was "clearly" something wrong :)

Should I expect the fix for the ClassNotFoundException coming to a stable release anytime soon?

Thank you very much!

@scottf
Copy link
Contributor

scottf commented Oct 24, 2023

Yeah, I'll merge that in and will be available in a couple weeks. As soon as I merge it will be available in the 2.17.1-SNAPSHOT

@scottf
Copy link
Contributor

scottf commented Oct 24, 2023

@Alfablos Merged #1022 Will be available in the next release.

@scottf scottf closed this as completed Oct 24, 2023
@Alfablos
Copy link
Author

Thank you :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
defect Suspected defect such as a bug or regression
Projects
None yet
Development

No branches or pull requests

2 participants