JBOSS 5.1 和 Eclipse 的 Web 服务中的 JNI 问题
我的团队正在 Eclipse(Indigo,构建 ID:20110615-0604)中创建一个针对 JBOSS 5.1(不可协商的服务器和客户定义的版本)应用程序服务器的 Web 服务。我公司的专有算法位于 Linux 64 位计算机上编译的共享库中,我需要从我的 Web 服务访问它们。我已经使用 SWIG 创建了 JNI 文件。生成的 java 文件被编译并放入 jar 中。该 jar 包含在 EAR 中,并且可供 Eclipse 中的所有项目查看。生成的 MODULE_wrap.cpp 文件被编译并包含在我的 .so 中 - 将其称为 libmylib.so
我的 Web 服务在启动时调用静态类以通过 System.loadLibrary("mylib") 加载我的共享库。这没有问题。我的库只加载一次,没有例外。我已经检查了我的库的路径是否在 java.library.path 属性中 - 正如 loadLibrary 工作以来所预期的那样。
生成的 SWIG 文件可与 Eclipse 外部的测试驱动程序一起使用 - 也就是说,我们可以访问库中的本机函数。这让我相信 SWIG 创建的函数名称和本机映射已正确完成。然而,当使用 Eclipse 创建 Web 服务 EAR 并将其部署到 JBOSS 时,我们收到 UnsatisfiedLinkError,抱怨无法找到我的库中的 C++ 构造函数。
我的 makefile 的 SWIG 行
swig -c++ -java -package my.package -outdir java/my/package -Isrc -Iinc -o src/MODULE_wrap.cpp src/MODULE.i
MODULE.i
/* File : MODULE.i */
%module MODULE
%include "arrays_java.i"
%apply double[] {double *};
%{
\#include "MyCPPHeader.hh"
%}
%include "MyCPPHeader.hh
我创建的共享对象:
g++ -fPIC -c -Idir1 -I. -Idir2 -Idir3 -Idir4 -Idir5 -O2 -DMACRO_DEF src/MyCPPSource.cpp -o obj/MyCPPSource.osh
g++ -fPIC -c -Idir1 -I. -Idir2 -Idir3 -Idir4 -Idir5 -O2 -DMACRO_DEF src/MODULE_wrap.cpp -o obj/MODULE_wrap.osh
我创建的库
g++ -shared -L/usr/lib/x86_64-redhat-linux5E/lib64 obj/MyCPPSource.osh obj/MODULE_wrap.osh -o lib/libmylib.so
SWIG .JAR
如果我对包含 SWIG 生成的 JAVA 文件的 jar 进行 jar -tf,则相应包目录结构中的所有必要类都在那里。 Eclipse/JBOSS 不会抱怨任何这些来源 - 仅当它尝试在 JNI 类中查找标记为“本机”的调用时。
加载库的java类。它位于 JAR 中的 JBoss'_Home/server/default/lib 中
public class LibLoader {
static
{
try
{
System.loadLibrary("mylib");
System.out.println("Loaded " + System.mapLibraryName("mylib"));
}
catch (java.lang.UnsatisfiedLinkError e)
{
System.out.println("Got unsat link error " + e.getMessage());
}
catch (Exception e)
{
System.out.println("Got exception " + e.getMessage());
}
}
public LibLoader() {}
}
如何从我的 Web 服务中使用该 LibLoader 类 - 它是作为 java 单例实现的:
public static WebService getInstance()
{
// loads library once outside the service
if (m_libLoader == null)
m_libLoader = new LibLoader();
// Create the singleton instance
if (m_instance == null)
m_instance = new WebService();
// Create an object as defined in my library and accessed with JNI
if (m_libraryObject == null)
{
// THIS IS WHERE I GET THE UnsatisfiedLinkError!!!!!
m_libraryObject = new MyObjectFromSharedLibrary();
}
return m_instance;
}
My team is creating a web service in Eclipse (Indigo with build id: 20110615-0604) targeted for the JBOSS 5.1 (non-negotiable server and version as defined by the customer) application server. My company's proprietary algorithms are in a shared library compiled on a Linux 64 bit machine and I need to access them from my web service. I've created my JNI files with SWIG. The resultant java files are compiled and dropped in a jar. The jar is included in the EAR and seen by all projects in Eclipse. The resultant MODULE_wrap.cpp file is compiled and included in my .so - call it libmylib.so
My web service, when it starts up, calls a static class to load my shared library via System.loadLibrary("mylib"). There are no issues with this. My library is only loaded once and there are no exceptions. I've checked that the path to my library is in the java.library.path property - as expected since loadLibrary worked.
The resultant SWIG files work with a test driver outside of Eclipse - that is we can access native functions in the library. This makes me believe that the function names created by SWIG and the native mapping are being done correctly. However, when using Eclipse to create and deploy the web service EAR to JBOSS we get an UnsatisfiedLinkError complaining that a C++ constructor from my library cannot be found.
SWIG line of my makefile
swig -c++ -java -package my.package -outdir java/my/package -Isrc -Iinc -o src/MODULE_wrap.cpp src/MODULE.i
MODULE.i
/* File : MODULE.i */
%module MODULE
%include "arrays_java.i"
%apply double[] {double *};
%{
\#include "MyCPPHeader.hh"
%}
%include "MyCPPHeader.hh
My creation of the shared objects:
g++ -fPIC -c -Idir1 -I. -Idir2 -Idir3 -Idir4 -Idir5 -O2 -DMACRO_DEF src/MyCPPSource.cpp -o obj/MyCPPSource.osh
g++ -fPIC -c -Idir1 -I. -Idir2 -Idir3 -Idir4 -Idir5 -O2 -DMACRO_DEF src/MODULE_wrap.cpp -o obj/MODULE_wrap.osh
My creation of the library
g++ -shared -L/usr/lib/x86_64-redhat-linux5E/lib64 obj/MyCPPSource.osh obj/MODULE_wrap.osh -o lib/libmylib.so
SWIG .JAR
If I do a jar -tf of the jar containing the SWIG generated JAVA files all of the necessary classes in the appropriate package directory structure are there. Eclipse/JBOSS don't complain about any of these sources - only when it attempts to find the call labeled as "native" in the JNI class.
The java class that loads the library. It lives in JBoss'_Home/server/default/lib within a JAR
public class LibLoader {
static
{
try
{
System.loadLibrary("mylib");
System.out.println("Loaded " + System.mapLibraryName("mylib"));
}
catch (java.lang.UnsatisfiedLinkError e)
{
System.out.println("Got unsat link error " + e.getMessage());
}
catch (Exception e)
{
System.out.println("Got exception " + e.getMessage());
}
}
public LibLoader() {}
}
How that LibLoader class is used from my web service - which is implemented as a java singleton:
public static WebService getInstance()
{
// loads library once outside the service
if (m_libLoader == null)
m_libLoader = new LibLoader();
// Create the singleton instance
if (m_instance == null)
m_instance = new WebService();
// Create an object as defined in my library and accessed with JNI
if (m_libraryObject == null)
{
// THIS IS WHERE I GET THE UnsatisfiedLinkError!!!!!
m_libraryObject = new MyObjectFromSharedLibrary();
}
return m_instance;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
已解决
我没有将 SWIG JNI 包装器 JAR 与我的 EAR 捆绑在一起,而是将其放在服务器上与我的 LibLoader JAR 相同的目录中,并且看到它工作了。
SOLVED
Instead of bundling the SWIG JNI wrapper JAR with my EAR I put it in the same directory on the server as my LibLoader JAR and low and behold it worked.