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

使用Maven javafx:jlink时出现com.sun.jna.Callback类找不到错误的原因

问题:JavaFX jlink打包后运行出现ClassNotFoundException: com.sun.jna.Callback

开发JavaFX应用(基于OpenJFX 19 + OpenJDK 11),使用javafx-maven-plugin的javafx:jlink命令打包,应用依赖非模块化的org.pcap4j(该库又依赖com.sun.jna)。手动为两个jar注入module-info.class后jlink执行成功,但运行生成的镜像时出现java.lang.ClassNotFoundException: com.sun.jna.Callback错误,调整模块声明和依赖关系无效,使用requires transitive时还出现Native层崩溃。


相关配置与操作

pom.xml中的JavaFX插件配置

<plugin>
        <groupId>org.openjfx</groupId>
        <artifactId>javafx-maven-plugin</artifactId>
        <version>0.0.8</version>
        <executions>
          <execution>
            <id>default-cli</id>
            <configuration>
              <mainClass>${mainclass}</mainClass>
              <launcher>app</launcher>
              <jlinkZipName>app</jlinkZipName>
              <jlinkImageName>app</jlinkImageName>
              <noManPages>true</noManPages>
              <stripDebug>true</stripDebug>
              <noHeaderFiles>true</noHeaderFiles>
              <stripDebug>true</stripDebug>
              <compress>2</compress>
              <launcher>${jlink-image-name}</launcher>
              <jlinkImageName>${jlink-image-name}</jlinkImageName>
              <mainClass>${mainclass}</mainClass>
            </configuration>
          </execution>
        </executions>
      </plugin>

pom.xml中的依赖配置

<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<!-- groupId etc. -->

<properties>
    <classifier>linux</classifier>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <javafx-graphics.version>19</javafx-graphics.version>
    <!-- etc. -->
</properties>


<!-- Openjfx -->
    <dependency>
      <groupId>org.openjfx</groupId>
      <artifactId>javafx-graphics</artifactId>
      <version>${javafx-graphics.version}</version>
      <classifier>${classifier}</classifier>
    </dependency>
    <dependency>
      <groupId>org.openjfx</groupId>
      <artifactId>javafx-controls</artifactId>
      <version>${javafx-graphics.version}</version>
      <classifier>${classifier}</classifier>
    </dependency>
<!-- Pcap4j (non-modular) -->
    <dependency>
      <groupId>org.pcap4j</groupId>
      <artifactId>pcap4j-core</artifactId>
      <version>1.7.4</version>
    </dependency>
<!-- com.sun.jna needed for Pcap4j (non-modular) -->
    <dependency>
      <groupId>net.java.dev.jna</groupId>
      <artifactId>jna</artifactId>
      <version>4.0.0</version>
    </dependency>
<!-- logging etc. -->
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.8.0-beta2</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-simple</artifactId>
      <version>1.8.0-beta2</version>
      <scope>test</scope>
    </dependency>
<!-- ... -->

</project>

将JNA转为模块化的操作

# 进入项目目录(IntelliJ IDEA)
jdeps --generate-module-info target //.../net/java/dev/jna/jna/4.0.0/jna-4.0.0.jar

javac --patch-module jna=//.../net/java/dev/jna/jna/4.0.0/jna-4.0.0.jar target/jna/module-info.jna

# 进入包含module-info.class的目录
jar uf //.../net/java/dev/jna/jna/4.0.0/jna-4.0.0.jar module-info.class

将Pcap4j转为模块化的操作

# 进入项目目录

jdeps --module-path //path/to/jna-4.0.0.jar://path/to/pcap4j-core-1.7.4-sources.jar
  ://path/to/slf4j-simple-1.8.0-beta2.jar
  ://path/to/slf4j-api-1.8.0-beta2.jar 
  --generate-module-info target //path/to/pcap4j-core-1.7.4.jar

javac --module-path //path/to/jna-4.0.0.jar
  ://path/to/slf4j-simple-1.8.0-beta2.jar
  ://path/to/pcap4j-core-1.7.4-sources.jar
  ://path/to/slf4j-api-1.8.0-beta2.jar
  ://path/to/pcap4j-core-1.7.4.jar 
  --patch-module pcap4j.core=//path/to/pcap4j-core-1.7.4.jar target/pcap4j.core/module-info.java 

# 进入包含module-info.class的目录
jar uf //path/to/pcap4j-core-1.7.4.jar module-info.class

运行应用时的错误

解压app.zip后执行./bin/app,报错如下:

SLF4J: No SLF4J providers were found.
SLF4J: Defaulting to no-operation (NOP) logger implementation
Exception in Application start method
Exiting
java.lang.reflect.InvocationTargetException
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.base/java.lang.reflect.Method.invoke(Unknown Source)
    at javafx.graphics@19/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(Unknown Source)
    at javafx.graphics@19/com.sun.javafx.application.LauncherImpl.launchApplication(Unknown Source)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.base/java.lang.reflect.Method.invoke(Unknown Source)
    at java.base/sun.launcher.LauncherHelper$FXHelper.main(Unknown Source)
Caused by: java.lang.RuntimeException: Exception in Application start method
    at javafx.graphics@19/com.sun.javafx.application.LauncherImpl.launchApplication1(Unknown Source)
    at javafx.graphics@19/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(Unknown Source)
    at java.base/java.lang.Thread.run(Unknown Source)
Caused by: java.lang.NoClassDefFoundError: com/sun/jna/Callback
    at java.base/java.lang.ClassLoader.defineClass1(Native Method)
    at java.base/java.lang.ClassLoader.defineClass(Unknown Source)
    at java.base/java.lang.ClassLoader.defineClass(Unknown Source)
    at java.base/java.security.SecureClassLoader.defineClass(Unknown Source)
    at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(Unknown Source)
    at java.base/jdk.internal.loader.BuiltinClassLoader.findClassInModuleOrNull(Unknown Source)
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(Unknown Source)
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(Unknown Source)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(Unknown Source)
    at java.base/java.lang.ClassLoader.loadClass(Unknown Source)
    at pcap4j.core/org.pcap4j.core.PcapHandle$Builder.build(Unknown Source)
    
        etc.etc.

    at javafx.graphics@19/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(Unknown Source)
    at javafx.graphics@19/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(Unknown Source)
    at javafx.graphics@19/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(Unknown Source)
    at java.base/java.security.AccessController.doPrivileged(Native Method)
    at javafx.graphics@19/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(Unknown Source)
    at javafx.graphics@19/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(Unknown Source)
    at javafx.graphics@19/com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
    at javafx.graphics@19/com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$11(Unknown Source)
    ... 1 more
Caused by: java.lang.ClassNotFoundException: com.sun.jna.Callback
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(Unknown Source)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(Unknown Source)
    at java.base/java.lang.ClassLoader.loadClass(Unknown Source)

JavaFX应用的module-info

module MyApp {

    requires javafx.controls;
    requires com.google.gson;
    requires org.slf4j;
    requires java.desktop;
    requires static com.sun.jna;
    requires pcap4j.core;


    opens ch.my.app to javafx.graphics, com.google.gson;
    exports ch.my.app;
    exports ch.my.app.xx;
    export etc.etc.;
}

已尝试的解决思路

  • 调整JNA模块名为com.sun.jna,同步修改pcap4j.core的requires static jna为requires static com.sun.jna,无效。
  • 在pcap4j.core的module-info中使用requires transitive jna,导致Native层崩溃:
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007fa9f0807604, pid=192519, tid=192548
#
# JRE version: OpenJDK Runtime Environment (11.0.19+7) (build 11.0.19+7-post-Ubuntu-0ubuntu118.04.1)
# Java VM: OpenJDK 64-Bit Server VM (11.0.19+7-post-Ubuntu-0ubuntu118.04.1, mixed mode, tiered, compressed oops, g1 gc, linux-amd64)
# Problematic frame:
# C  [jna10034915907313375652.tmp+0x7604]
#
# Core dump will be written. Default location: Core dumps may be processed with "/usr/share/apport/apport -p%p -s%s -c%c -d%d -P%P -u%u -g%g -- %E" (or dumping to /path/to/app/core.192519)
#
# An error report file with more information is saved as:
# /path/to/app/hs_err_pid192519.log
#
Aborted (core dumped)

问题原因与解决方案

原因分析

  1. 模块导出缺失:自动生成的JNA module-info未导出com.sun.jna等核心包,导致pcap4j运行时无法访问相关类。
  2. requires static误用:requires static仅保证编译期依赖,运行时不会自动包含该模块,但pcap4j运行时必须依赖JNA,因此该声明不适用。
  3. JNA版本兼容性:JNA 4.0.0版本过旧,与Java模块系统兼容性差,易出现Native层加载崩溃问题。

解决方案

1. 修正JNA的module-info

手动编写JNA的module-info,确保导出所有必要包并开放给pcap4j访问:

module com.sun.jna {
    exports com.sun.jna;
    exports com.sun.jna.ptr;
    exports com.sun.jna.platform;
    opens com.sun.jna to pcap4j.core;
    opens com.sun.jna.ptr to pcap4j.core;
    requires java.base;
}

重新编译该文件,用jar uf注入到JNA jar中。

2. 修正pcap4j.core的module-info

将依赖声明改为requires transitive com.sun.jna,确保依赖传递到应用模块:

module pcap4j.core {
    requires transitive com.sun.jna;
    requires org.slf4j;
    exports org.pcap4j.core;
    opens org.pcap4j.core to MyApp;
}

重新编译并注入到pcap4j-core jar中。

3. 修正应用的module-info

移除requires static com.sun.jna,通过pcap4j.core的requires transitive自动引入JNA:

module MyApp {
    requires javafx.controls;
    requires com.google.gson;
    requires org.slf4j;
    requires java.desktop;
    requires pcap4j.core;

    opens ch.my.app to javafx.graphics, com.google.gson;
    exports ch.my.app;
    exports ch.my.app.xx;
    // 其他导出/声明
}

4. 升级JNA版本

将JNA版本升级到5.x及以上(如5.13.0),新版本原生支持模块系统,无需手动注入module-info,且能避免Native层崩溃:

<dependency>
    <groupId>net.java.dev.jna</groupId>
    <artifactId>jna</artifactId>
    <version>5.13.0</version>
</dependency>

5. 调整javafx-maven-plugin配置

添加modulePath配置,明确依赖模块路径:

<plugin>
    <groupId>org.openjfx</groupId>
    <artifactId>javafx-maven-plugin</artifactId>
    <version>0.0.8</version>
    <executions>
        <execution>
            <id>default-cli</id>
            <configuration>
                <mainClass>${mainclass}</mainClass>
                <launcher>app</launcher>
                <jlinkZipName>app</jlinkZipName>
                <jlinkImageName>app</jlinkImageName>
                <noManPages>true</noManPages>
                <stripDebug>true</stripDebug>
                <noHeaderFiles>true</noHeaderFiles>
                <compress>2</compress>
                <modulePath>
                    <modulePathElement>${maven.dependency.classpath}</modulePathElement>
                </modulePath>
            </configuration>
        </execution>
    </executions>
</plugin>

6. 重新执行打包命令

清理缓存后重新构建打包:

mvn clean
mvn javafx:jlink

内容的提问来源于stack exchange,提问作者Ayame4

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 23:33:09