Java问题加载本机Lib内部罐子里

发布于 2025-01-25 17:35:44 字数 3544 浏览 1 评论 0原文

(我发现我只需要一个本地lib,而不是以前想象的所有4个,我稍作重新编辑了我的帖子

。 “ https://stackoverflow.com/a/49500154/19018243"> this 代码(顺便说一句,我也基本上尝试了该页面中的所有其他代码 - 在我的情况下,所有这些代码都相同!!! 。

我的改装代码看起来像这样:

static {
    try {
        //EXTRACT NATIVE LIB(S) FROM JAR
        String libName = "lwjgl64.dll";
        URL url = Class.class.getResource("/natives/" + libName);
        File tmpDir = new File(App.FILE_APPPATH.getAbsolutePath() + "/libs");
        if (tmpDir.exists()) {
            FileUtils.deleteDirectory(tmpDir);
        }
        tmpDir.mkdir();
        File nativeLibTmpFile = new File(tmpDir, libName);
        try (InputStream in = url.openStream()) {
            Files.copy(in, nativeLibTmpFile.toPath());
        }

        //ADD PATH TO EXTRACTED LIBS FOLDER TO JAVA
        System.setProperty("java.library.path", tmpDir.getAbsolutePath());
        Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths");
        fieldSysPath.setAccessible(true);
        fieldSysPath.set(null, null);
        //System.err.println("'" + System.getProperty("java.library.path") + "'");

        //LOAD LIB DLL FILE(S)
        //System.err.println("'" + nativeLibTmpFile.getAbsolutePath() + "'");
        System.load(nativeLibTmpFile.getAbsolutePath());
    } catch (IOException | SecurityException | IllegalArgumentException | NoSuchFieldException | IllegalAccessException  ex) {
        Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
    }
}

我将此代码添加到我的主类中,然后从Netbeanside运行我的Java应用程序 - 像这样运行我的Java应用程序似乎还可以,而且工作正常,没有任何错误,

但是当我编译项目/时应用程序要运行它(现在已经以蝙蝠文件启动的Netbeanside之外),然后一旦有一个方法或函数要求本机Lib我得到这个错误:

Exception in thread "Thread-12" java.lang.NoClassDefFoundError: org/lwjgl/system/FunctionProvider
        at org.lwjgl.opengl.GL11.<clinit>(GL11.java:38)
        at org.lwjgl.opengl.GLContext.getSupportedExtensions(GLContext.java:228)
        at org.lwjgl.opengl.ContextCapabilities.initAllStubs(ContextCapabilities.java:5802)
        at org.lwjgl.opengl.ContextCapabilities.<init>(ContextCapabilities.java:6240)
        at org.lwjgl.opengl.GLContext.useContext(GLContext.java:374)
        at org.lwjgl.opengl.ContextGL.makeCurrent(ContextGL.java:195)
        at org.lwjgl.opengl.DrawableGL.makeCurrent(DrawableGL.java:110)
        at org.lwjgl.opengl.Display.makeCurrent(Display.java:706)
        at org.lwjgl.opengl.Display.makeCurrentAndSetSwapInterval(Display.java:1025)
        at org.lwjgl.opengl.Display.create(Display.java:852)
        at org.lwjgl.opengl.Display.create(Display.java:797)
        ...

由此我,我会说它仍然不知道在哪里本地lib是 - 对吗?我仔细检查了当我的应用程序通过BAT文件启动时,将本机LIB成功从JAR中提取到指定的创建目录...是的。

我的蝙蝠文件代码看起来像这样:

@ECHO OFF
java -XX:+UseG1GC -Xmx1G -server -jar data.jar %*
@if %errorlevel% neq 0 pause

如何按照Netbeanside运行时的预期完美工作,但无法找到/负载已经成功提取并正确添加了本机LIB文件(已经通过上面的代码直接从应用程序内部添加了它)?

谁能告诉我我的代码有什么问题或如何正确制造?

也许蝙蝠文件中的某些值在使用本机libs时不应该存在的值(请记住,我不需要将-djava.library.path添加到我的蝙蝠文件中罐子里的lib)?您看到:我以前从未使用过本地libs,这是我第一次。

顺便说一句,我还试图将-djava.library.path带到蝙蝠中,带有本机LIB的绝对路径(我没有路径中的空格),但结果绝对是同样的...奇怪的是,就像在操作系统中阻止访问的东西,我必须立即说不说,因为从Netbeanside访问它没有问题 - 这确实是针对编译的最终Jar File + Bat(或在至少这就是我目前看到的)。

更新2022-05-06

在其他几项测试之后,我非常接近我认为实际上可能是由Windows 7 X64 OS引起的,该X64 OS处理了文件权限, /stackoverflow.com/q/39545766/19018243"> dll文件权限原因发帖。 但是,如果是这样,那么其他人在用本机Libs部署其Java应用程序时又没有问题……还是真的是某种Windows 7 X64特定问题? 另外,我不知道如何使它起作用,因为我已经为我的Java项目的整个目录添加了完全许可,但它的行为仍然相同。

(I slightly re-edited my post as I found out that I need just one native lib, not all 4 as previously thought)

I am on Windows 7 x64, and I try to pack my native lib into the JAR using this code (BTW I also tried basically all the other codes from that page - result the same for all of them in my case!!!).

My modded code looks like this:

static {
    try {
        //EXTRACT NATIVE LIB(S) FROM JAR
        String libName = "lwjgl64.dll";
        URL url = Class.class.getResource("/natives/" + libName);
        File tmpDir = new File(App.FILE_APPPATH.getAbsolutePath() + "/libs");
        if (tmpDir.exists()) {
            FileUtils.deleteDirectory(tmpDir);
        }
        tmpDir.mkdir();
        File nativeLibTmpFile = new File(tmpDir, libName);
        try (InputStream in = url.openStream()) {
            Files.copy(in, nativeLibTmpFile.toPath());
        }

        //ADD PATH TO EXTRACTED LIBS FOLDER TO JAVA
        System.setProperty("java.library.path", tmpDir.getAbsolutePath());
        Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths");
        fieldSysPath.setAccessible(true);
        fieldSysPath.set(null, null);
        //System.err.println("'" + System.getProperty("java.library.path") + "'");

        //LOAD LIB DLL FILE(S)
        //System.err.println("'" + nativeLibTmpFile.getAbsolutePath() + "'");
        System.load(nativeLibTmpFile.getAbsolutePath());
    } catch (IOException | SecurityException | IllegalArgumentException | NoSuchFieldException | IllegalAccessException  ex) {
        Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
    }
}

I added this code to my main class, and run my Java app from the NetBeansIDE - running my java App like this all seem to be OK and working correctly, no error whatsoever

But when I compile my project/App to JAR, run it (that is now already outside the NetBeansIDE started by BAT file) then as soon as there is a method or function that requires that native lib I got this error:

Exception in thread "Thread-12" java.lang.NoClassDefFoundError: org/lwjgl/system/FunctionProvider
        at org.lwjgl.opengl.GL11.<clinit>(GL11.java:38)
        at org.lwjgl.opengl.GLContext.getSupportedExtensions(GLContext.java:228)
        at org.lwjgl.opengl.ContextCapabilities.initAllStubs(ContextCapabilities.java:5802)
        at org.lwjgl.opengl.ContextCapabilities.<init>(ContextCapabilities.java:6240)
        at org.lwjgl.opengl.GLContext.useContext(GLContext.java:374)
        at org.lwjgl.opengl.ContextGL.makeCurrent(ContextGL.java:195)
        at org.lwjgl.opengl.DrawableGL.makeCurrent(DrawableGL.java:110)
        at org.lwjgl.opengl.Display.makeCurrent(Display.java:706)
        at org.lwjgl.opengl.Display.makeCurrentAndSetSwapInterval(Display.java:1025)
        at org.lwjgl.opengl.Display.create(Display.java:852)
        at org.lwjgl.opengl.Display.create(Display.java:797)
        ...

From this I would say it still does not know where the native lib is - right? I double checked that the native lib is successfully extracted from the JAR to specified created directory when my app is started via BAT file...and yes, it is.

My BAT file code looks like this:

@ECHO OFF
java -XX:+UseG1GC -Xmx1G -server -jar data.jar %*
@if %errorlevel% neq 0 pause

How come it works perfectly as expected when run from NetBeansIDE but it is unable to locate/load already successfully extracted and correctly added native lib file (it is already added directly from inside the app via the code above)?

Can anyone tell me what is wrong with my code or how to make it correctly?

Maybe some values in the BAT file that should not be there when one is using native libs (remember that I do not need to add -Djava.library.path to my BAT file as I have packed my native lib inside the JAR)? You see: I never used native libs before, this is my first time ever.

BTW I also tried to add that -Djava.library.path to the BAT with the absolute path to the folder with the native libs (I have no spaces in the path), yet the result is absolutely the same...strange, like something in the OS preventing the access tho i have to immediately say probably not, cos it has no problem accessing it from the NetBeansIDE - this is really specific just to the compiled final JAR file + BAT (or at least that is how I see it at the moment).

UPDATE 2022-05-06

After several other tests I am very close to believe this issue might actually be caused by the Windows 7 x64 OS dealing with file permissions, according to DLL file permissions causes not working post.
But if that is the case, how come others have no such problems when deploying their java apps with native libs...or is it really some sort of Windows 7 x64 specific issue?
Also I do not know how to make it work cos I already added full permission for the whole directory of my java projects yet it still behaves the same.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

锦上情书 2025-02-01 17:35:44

首先取消一些好的建议:

  • 从项目中删除所有不必要的JAR文件(它们可能会导致类似于您的问题)
  • 不要混合不同版本的lwjgl jar文件(可能导致与您的问题相似)
  • 不会混合不同版本的LWJGL本机.dll .dll .dll .dll文件(可能导致与您的问题类似)
  • 仅使用真正需要的本机.dll文件(某些不必要的文件可能会导致像您这样的错误)

现在,这里是我更新您的代码,以自动检测内部本地文件夹中的所有本机文件而无需手动定义它们 +基本上是您的 - 经过测试,所有这些都应尽可能地工作。

//INITIALIZATION OF NATIVE LIBS PACKED INSIDE THE COMPILLED JAR
static {
    try {
        String internalNativesFolder = "natives";

        //EXTRACT NATIVE LIB(S) FROM JAR
        File tmpDir = new File(App.FILE_APPPATH.getAbsolutePath() + App.LOMKA_R + internalNativesFolder);
        if (tmpDir.exists()) {
            FileUtils.deleteDirectory(tmpDir);
        }
        tmpDir.mkdir();

        //GETS ALL FILES IN INTERNAL NATIVES FOLDER
        URI uri = App.class.getResource(App.LOMKA_R + internalNativesFolder).toURI();
        Path myPath;
        if (uri.getScheme().equals("jar")) {
            FileSystem fileSystem = FileSystems.newFileSystem(uri, Collections.<String, Object>emptyMap());
            myPath = fileSystem.getPath(App.LOMKA_R + internalNativesFolder);
        } else {
            myPath = Paths.get(uri);
        }
        Stream<Path> walk = Files.walk(myPath, 1);
        List<String> libNames = new ArrayList<>();
        for (Iterator<Path> it = walk.iterator(); it.hasNext();) {
            String fN = it.next().getFileName().toString();
            if (!fN.equals(internalNativesFolder)) {
                libNames.add(fN);
            }
        }

        //COPIES THOSE FILES TO TEMPORARY LOCAL DIRECTORY
        for (String libName : libNames) {
            URL url = Class.class.getResource(App.LOMKA_R + internalNativesFolder + App.LOMKA_R + libName);
            File nativeLibTmpFile = new File(tmpDir, libName);
            try (InputStream in = url.openStream()) {
                Files.copy(in, nativeLibTmpFile.toPath());
            }
        }

        //ADD PATH TO EXTRACTED LIBS FOLDER TO JAVA
        System.setProperty("java.library.path", tmpDir.getAbsolutePath());
        Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths");
        fieldSysPath.setAccessible(true);
        fieldSysPath.set(null, null);

        //LOAD LIB DLL FILE(S)
        libNames.forEach(libName -> {
            System.load(new File(tmpDir, libName).getAbsolutePath());
        });

    } catch (IOException | SecurityException | IllegalArgumentException | NoSuchFieldException | IllegalAccessException | URISyntaxException ex) {
        Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
    }
}

First off some good advices:

  • remove all unnecessary jar files from your project (they might cause problems similar to yours)
  • do not mix different versions of LWJGL jar files (might cause problems similar to yours)
  • do not mix different versions of LWJGL native .dll files (might cause problems similar to yours)
  • use only really needed native .dll files (sometime unnecessary ones may cause errors like yours)

Now here is your code updated by me for automatic detection of all native files in internal natives folder without need of manually defining them + rest is basically yours - tested myself, all works as it should.

//INITIALIZATION OF NATIVE LIBS PACKED INSIDE THE COMPILLED JAR
static {
    try {
        String internalNativesFolder = "natives";

        //EXTRACT NATIVE LIB(S) FROM JAR
        File tmpDir = new File(App.FILE_APPPATH.getAbsolutePath() + App.LOMKA_R + internalNativesFolder);
        if (tmpDir.exists()) {
            FileUtils.deleteDirectory(tmpDir);
        }
        tmpDir.mkdir();

        //GETS ALL FILES IN INTERNAL NATIVES FOLDER
        URI uri = App.class.getResource(App.LOMKA_R + internalNativesFolder).toURI();
        Path myPath;
        if (uri.getScheme().equals("jar")) {
            FileSystem fileSystem = FileSystems.newFileSystem(uri, Collections.<String, Object>emptyMap());
            myPath = fileSystem.getPath(App.LOMKA_R + internalNativesFolder);
        } else {
            myPath = Paths.get(uri);
        }
        Stream<Path> walk = Files.walk(myPath, 1);
        List<String> libNames = new ArrayList<>();
        for (Iterator<Path> it = walk.iterator(); it.hasNext();) {
            String fN = it.next().getFileName().toString();
            if (!fN.equals(internalNativesFolder)) {
                libNames.add(fN);
            }
        }

        //COPIES THOSE FILES TO TEMPORARY LOCAL DIRECTORY
        for (String libName : libNames) {
            URL url = Class.class.getResource(App.LOMKA_R + internalNativesFolder + App.LOMKA_R + libName);
            File nativeLibTmpFile = new File(tmpDir, libName);
            try (InputStream in = url.openStream()) {
                Files.copy(in, nativeLibTmpFile.toPath());
            }
        }

        //ADD PATH TO EXTRACTED LIBS FOLDER TO JAVA
        System.setProperty("java.library.path", tmpDir.getAbsolutePath());
        Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths");
        fieldSysPath.setAccessible(true);
        fieldSysPath.set(null, null);

        //LOAD LIB DLL FILE(S)
        libNames.forEach(libName -> {
            System.load(new File(tmpDir, libName).getAbsolutePath());
        });

    } catch (IOException | SecurityException | IllegalArgumentException | NoSuchFieldException | IllegalAccessException | URISyntaxException ex) {
        Logger.getLogger(App.class.getName()).log(Level.SEVERE, null, ex);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文