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

能否将Java的java.library.path设置为程序的resources资源文件夹?

LWJGL 2 内嵌原生库到Jar的实现方案

完全可以实现,核心逻辑是启动时将resources内的原生库解压到临时目录,手动注入JVM的库搜索路径,不需要把dll和jar放在同一目录。

第一步:Gradle项目配置

  • 将对应平台的LWJGL 2原生库(dll/so/dylib)放到src/main/resources/natives/目录下,建议按平台分分子目录,比如windows平台的库存放为src/main/resources/natives/windows/,linux存natives/linux/,mac存natives/macos/。
  • 调整build.gradle配置,确保资源正常打包进Jar:
apply plugin: 'java'

dependencies {
    // 替换为你实际使用的LWJGL 2版本,无需引入官方分平台的natives依赖包
    implementation 'org.lwjgl.lwjgl:lwjgl:2.9.3'
}

jar {
    from sourceSets.main.resources
    manifest {
        // 替换为你自己的主类全限定名
        attributes 'Main-Class': 'com.yourpkg.Main'
    }
}

第二步:编写原生库加载工具类

在调用任何LWJGL相关代码前,先执行加载逻辑:读取classpath内的原生文件,拷贝到系统临时目录,再将临时目录注册为JVM库搜索路径。代码可以直接复用:

import java.io.*;
import java.lang.reflect.Field;
import java.nio.file.*;
import java.util.Locale;

public class LWJGLNativeLoader {
    private static boolean isLoaded = false;

    public static void load() throws Exception {
        if (isLoaded) return;

        // 识别当前运行的操作系统
        String os = System.getProperty("os.name").toLowerCase(Locale.ROOT);
        String nativeSubPath;
        if (os.contains("win")) {
            nativeSubPath = "/natives/windows";
        } else if (os.contains("mac") || os.contains("darwin")) {
            nativeSubPath = "/natives/macos";
        } else if (os.contains("nix") || os.contains("nux")) {
            nativeSubPath = "/natives/linux";
        } else {
            throw new RuntimeException("不支持当前系统: " + os);
        }

        // 创建临时目录存放解压的原生库,JVM退出时自动删除
        Path tempDir = Files.createTempDirectory("lwjgl2-natives");
        tempDir.toFile().deleteOnExit();

        // 逐个拷贝原生库到临时目录,这里替换为你实际放入resources的原生库文件名
        String[] libNames;
        if (os.contains("win")) {
            libNames = new String[]{"lwjgl.dll", "OpenAL32.dll", "jinput-dx8.dll", "jinput-raw.dll"};
        } else if (os.contains("mac")) {
            libNames = new String[]{"liblwjgl.dylib", "libopenal.dylib", "libjinput-osx.jnilib"};
        } else {
            libNames = new String[]{"liblwjgl.so", "libopenal.so", "libjinput-linux.so"};
        }

        for (String libName : libNames) {
            Path targetPath = tempDir.resolve(libName);
            try (InputStream in = LWJGLNativeLoader.class.getResourceAsStream(nativeSubPath + "/" + libName)) {
                if (in == null) continue;
                Files.copy(in, targetPath, StandardCopyOption.REPLACE_EXISTING);
                targetPath.toFile().deleteOnExit();
            }
        }

        // 将临时目录加入JVM库搜索路径
        String originPath = System.getProperty("java.library.path");
        System.setProperty("java.library.path", tempDir.toAbsolutePath() + File.pathSeparator + originPath);

        // 刷新类加载器的路径缓存,否则上面的配置不会生效
        Field sysPathField = ClassLoader.class.getDeclaredField("sys_paths");
        sysPathField.setAccessible(true);
        sysPathField.set(null, null);

        isLoaded = true;
    }
}

注意:不要尝试用File对象直接读取Jar包内的资源,Jar是压缩包格式,classpath资源必须通过类加载器的流接口读取。写死要加载的库文件名是兼容性最高的方案,不会出现IDE能运行、打Jar就找不到文件的问题。

第三步:调整初始化顺序

在主方法的最开头调用加载方法,必须在任何LWJGL类被加载前执行,否则JVM会提前触发原生库查找直接报错:

public class Main {
    public static void main(String[] args) throws Exception {
        // 第一行就执行加载
        LWJGLNativeLoader.load();

        // 后面正常写LWJGL初始化逻辑即可
        // Display.setDisplayMode(new DisplayMode(800, 600));
        // Display.create();
    }
}

常见踩坑点

  • 内嵌的原生库版本必须和引入的lwjgl.jar版本完全一致,否则会报版本不匹配错误
  • 如果使用Slick2D等基于LWJGL 2的二次封装库,也要保证在初始化这些库之前先执行加载逻辑
  • 打Jar后如果提示找不到库,先解压Jar检查natives目录下的文件是否被正确打包、路径是否和代码里写的一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 04:54:37