从Grails应用程序使用JNI本机库时出现UnsatisfiedLinkError [英] UnsatisfiedLinkError when using a JNI native library from Grails application

查看:244
本文介绍了从Grails应用程序使用JNI本机库时出现UnsatisfiedLinkError的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个应用程序需要使用本地库: libfoo.so



我的代码是如下所示:

Accessor.java:

  public class Accessor {
static {
String path =/usr/lib/libfoo.so;
System.load(path);
}
...
}

当我在独立的tomcat服务器上部署我的war文件时。



问题在于当我运行嵌入式tomcat服务器时:

  grails run-app 

我收到一个UnsatisfiedLinkError:

 引起UnsatisfiedLinkError:com.foo.bar.GFS_MALJNI.new_Accessor__SWIG_0(Ljava / lang / String; I )J 
- >> 39 | < INIT>在com.foo.bar.Accessor

中有趣的是,如果我将 BuildConfig.groovy 文件转换为fork模式,它也可以工作。

BuildConfig.groovy:

  grails.project.fork = [
run:[maxMemory:1024,minMemory:64,debug:false,maxPerm:256]
]

我不想在fork模式下运行它。

解决方案

我注意到正在使用两个不同的类加载器。



模式下,正在使用这个类加载器: java.net.URLClassLoader



在分叉模式下,正被使用: groovy.lang.GroovyClassLoader



原生库在分叉模式下正常工作,所以我需要来创建一个hack来以非分叉模式加载GroovyClassLoader的库。



这就是在JDK S中定义System.load的方式ource:

System.java:

 public final class System {
...
public static void load(String filename){
Runtime.getRuntime()。load0(getCallerClass(),文件名);
}
...
}

调用 load0 与类加载器和文件名。显而易见的解决方案是使用自己的类加载器调用 load0 ,但由于它是受封装保护的,因此无法调用它。



在groovy中编写代码时,您可以访问受打包保护的私有方法/变量。

我可以指定自己的类加载器并加载库,如下所示:

  class Accessor {
static {
String path =/usr/lib/libfoo.so
//System.load(path);
Runtime.getRuntime()。load0(groovy.lang.GroovyClassLoader.class,path)
}
...
}

我只是试过了,它在非分叉模式下工作。


I have an application where I need to use a Native Library: libfoo.so

My code is as follows:

Accessor.java:

public class Accessor {        
    static {
        String path = "/usr/lib/libfoo.so";
        System.load(path);
    }
    ...
}

This works perfectly fine when I deploy my war file in a standalone tomcat server.

The problem is when I try to run the embedded tomcat server when you run:

grails run-app

I get an UnsatisfiedLinkError:

Caused by UnsatisfiedLinkError: com.foo.bar.GFS_MALJNI.new_Accessor__SWIG_0(Ljava/lang/String;I)J
->>   39 | <init>    in com.foo.bar.Accessor 

Interestingly enough, if I change my BuildConfig.groovy file to fork mode, it also works.

BuildConfig.groovy:

grails.project.fork = [
   run: [maxMemory:1024, minMemory:64, debug:false, maxPerm:256]
]

I do not want to run it in fork mode.

解决方案

I noticed that two different class loaders are being used.

In the non-forked mode, this class loader was being used: java.net.URLClassLoader

In the forked mode, this class loader was being used: groovy.lang.GroovyClassLoader

The native library works correctly in the forked mode, so I needed to come up with a hack to load the library with the GroovyClassLoader in the non-forked mode.

This is how System.load is defined in the JDK Source:

System.java:

public final class System {
    ...
    public static void load(String filename) {
        Runtime.getRuntime().load0(getCallerClass(), filename);
    }
    ...
}

It's calling load0 with the classloader and filename. The obvious solution is to call load0 with your own classloader, but you can't call it since it is package-protected.

When you write code in groovy, you have access to packge-protected and private methods/variables.

I can specify my own classloader and load the library, as such:

class Accessor {        
    static {
        String path = "/usr/lib/libfoo.so"
        //System.load(path);
        Runtime.getRuntime().load0(groovy.lang.GroovyClassLoader.class, path)
    }
    ...
}

I just tried it, and it's working in non-forked mode.

这篇关于从Grails应用程序使用JNI本机库时出现UnsatisfiedLinkError的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆