Native Library /usr/lib/libJMagick.so already loaded in another classloader

本文详细介绍了在JBoss环境中,当多个web应用需要使用相同的JNI本地库时,如何避免出现NativeLibrary已加载到另一个类加载器中的错误。通过将JNI类单独发布为jar包并放置于JBossAS配置的lib目录中,可以解决此类问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近安装了ImageMagick的应用服务器报如下异常:

java.lang.UnsatisfiedLinkError: Native Library /usr/lib/libJMagick.so already loaded in another classloader
	java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1772)
	java.lang.ClassLoader.loadLibrary(ClassLoader.java:1732)
	java.lang.Runtime.loadLibrary0(Runtime.java:823)
	java.lang.System.loadLibrary(System.java:1028)
	magick.Magick.<clinit>(Magick.java:38)
	com.xxx.ImageUtils.filterImage(ImageUtils.java:136)
	com.xxx.ImageUtils.isImageValid(ImageUtils.java:363)
	com.xxx.web.module.active.action.ActiveManagerAction.addActive(ActiveManagerAction.java:180)
	sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	java.lang.reflect.Method.invoke(Method.java:597)
	com.opensymphony.xwork2.DefaultActionInvocation.invokeAction(DefaultActionInvocation.java:452)
	com.opensymphony.xwork2.DefaultActionInvocation.invokeActionOnly(DefaultActionInvocation.java:291)
	com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:254)
	com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor.doIntercept(DefaultWorkflowInterceptor.java:176)
	com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
	com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)
	com.opensymphony.xwork2.validator.ValidationInterceptor.doIntercept(ValidationInterceptor.java:263)
	org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.doIntercept(AnnotationValidationInterceptor.java:68)
	com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
	com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)
	com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor.intercept(ConversionErrorInterceptor.java:133)
	com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)
	com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:207)
	com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
	com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)
	com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:207)
	com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:98)
	com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)
	com.opensymphony.xwork2.interceptor.StaticParametersInterceptor.intercept(StaticParametersInterceptor.java:190)
	com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)
	org.apache.struts2.interceptor.MultiselectInterceptor.intercept(MultiselectInterceptor.java:75)
	com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)
	org.apache.struts2.interceptor.CheckboxInterceptor.intercept(CheckboxInterceptor.java:94)
	com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:248)
	org.apache.struts2.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:314)

环境为:RedHat AS4,Jboss4.2.3,根据libJMagick.so already loaded in another classloader提示查找了相关资料得知,Jboss里面classload机制如下:

1、症状
      如果JBoss上的两个web应用需要使用相同的JNI本地库,当第二个web应用加载JNI本地库时,就会出现Native Library xxx.so already loaded in another classloader错误
2、原因
     Java虚拟机为了在JNI本地库中确保基于classloader的命名空间隔离,因而不允许一个JNI本地库被两个不同的classloader加载。而JBoss中web应用的classloader是独立的,也就是说每个web应用都有一个专属的classloader,这样就出现两个classloader加载同一JNI本地库的情况
3、解决方法
      在JBoss AS中,虽然不同的web应用使用不同的classloader,但是web应用classloader的父classloader是相同的,这样根据双亲委托模型只要让父classloader加载JNI本地库就可以避免被多个classloader加载。父classloader的classpath为JBoss AS配置(default、all或minimal)的lib目录,因而只要将JNI class单独发布成jar包,并放在配置(default、all或minimal)的lib目录中,问题就可以解决

但我们Jboss配置了4个实例,但当时只启了一个,不应该存在上述情况,故通过询问SCM得知,他对报异常的应用做了热部署,所以根据猜想应该是在热部署是原来的类已经加载了,此时又去加载,从而造成上述现象。

参考资料:

Jboss ClassLoader说明:http://community.jboss.org/wiki/JBossClassLoadingUseCases


<think>好的,用户在执行 `sudo ln -sv /usr/lib64/libmad.so.0.2.1 /usr/lib64/libmad.so.0` 时遇到了报错。首先,我需要理解这个命令的作用。`ln -s` 是创建符号链接的命令,这里用户试图将 `libmad.so.0.2.1` 链接到 `libmad.so.0`。报错可能的原因有几个,我需要逐一分析。 首先,检查源文件是否存在。用户指定的源文件是 `/usr/lib64/libmad.so.0.2.1`,可能这个文件不存在或者路径错误。接下来,目标文件 `/usr/lib64/libmad.so.0` 可能已经存在,导致无法创建链接。另外,权限问题也可能导致失败,虽然用户用了 `sudo`,但目录权限是否有问题?还有,是否有其他系统配置阻止了符号链接的创建? 接下来,我需要考虑用户可能的操作环境。用户之前尝试了 `ldd` 检查 sox 的依赖,可能是在处理音频文件时遇到问题,比如无法处理 MP3 文件,这可能是因为缺少相应的库或者链接不正确。用户之前可能已经安装了 `libmad` 和 `lame`,但链接没有正确建立,导致 sox 无法找到这些库。 用户现在遇到的具体问题是创建符号链接时报错,常见的错误信息可能包括“文件已存在”或“没有那个文件或目录”。我需要引导用户检查这两个可能性。如果目标文件已存在,可能需要删除或备份;如果源文件不存在,可能需要重新安装库或者查找正确的路径。 此外,用户可能对 Linux 的库管理不太熟悉,需要解释清楚符号链接的作用,以及为什么需要创建这样的链接。动态链接库通常使用主版本号和次版本号的链接,比如 `libmad.so.0` 指向具体的版本 `libmad.so.0.2.1`,这样程序在链接时可以使用较通用的名称,而不需要指定具体版本。 在处理这个问题时,还需要考虑用户是否在正确的目录下执行命令,是否有拼写错误,比如库名称是否正确,路径是否正确。例如,`/usr/lib64/` 是64位系统常见的库目录,但有些系统可能使用 `/usr/lib/`,尤其是32位系统或某些发行版的不同配置。 另外,用户可能之前按照某些教程或指南操作,但步骤可能有误,或者库的版本更新导致路径变化。比如,`libmad` 的安装路径可能不同,或者版本号不一致,导致源文件路径不正确。 最后,如果以上步骤都正确,可能需要更新动态链接器的缓存,使用 `sudo ldconfig` 来刷新库的链接,确保系统能够识别新创建的符号链接。</think>### **问题分析** 执行 `sudo ln -sv /usr/lib64/libmad.so.0.2.1 /usr/lib64/libmad.so.0` 报错时,主要原因是 **目标文件已存在** 或 **源文件路径错误**。以下是详细解析和解决方案: --- ### **错误类型及解决方案** | 错误类型 | 验证方法 | 解决方案 | |-----------------------|-------------------------------------------------------------------------|-------------------------------------------------------------------------| | **目标文件已存在** | `ls -l /usr/lib64/libmad.so.0` | 删除旧链接:`sudo rm -v /usr/lib64/libmad.so.0`,再重新执行 `ln` 命令 | | **源文件不存在** | `ls /usr/lib64/libmad.so.0.2.1` | 重新安装库:`sudo yum reinstall libmad`,确认库文件路径 | | **权限不足** | `ls -ld /usr/lib64/` | 检查目录权限(需 `rwx` 权限),或通过 `sudo -i` 切换到 root 环境执行 | | **路径拼写错误** | 检查命令中 `.so` 后缀和版本号是否完全匹配 | 使用 TAB 键补全路径:`sudo ln -sv /usr/lib64/libmad.so<TAB>` | --- ### **分步操作演示** #### **1. 验证目标文件是否存在** ```bash # 检查目标文件是否已存在 ls -l /usr/lib64/libmad.so.0 # 若输出类似: # lrwxrwxrwx 1 root root 19 Jun 10 09:00 /usr/lib64/libmad.so.0 -> libmad.so.0.2.1 # 则需要先删除旧链接 sudo rm -v /usr/lib64/libmad.so.0 ``` #### **2. 确认源文件存在性** ```bash # 检查源文件是否存在 ls /usr/lib64/libmad.so.0.2.1 # 若输出 "No such file or directory",说明: # - libmad 未正确安装 # - 版本号不匹配(如实际文件是 libmad.so.0.2.2) # 重新安装并确认路径 sudo yum reinstall libmad rpm -ql libmad | grep .so # 查看实际安装路径 ``` #### **3. 修复路径差异** ```bash # 如果库实际路径不同(例如在 /usr/lib/) sudo ln -sv /usr/lib/libmad.so.0.2.1 /usr/lib64/libmad.so.0 # 强制覆盖已存在文件(谨慎使用) sudo ln -sfv /usr/lib64/libmad.so.0.2.1 /usr/lib64/libmad.so.0 ``` #### **4. 更新动态链接缓存** ```bash # 确保系统识别新链接 sudo ldconfig # 验证链接是否生效 ls -l /usr/lib64/libmad.so.0 ldd $(which sox) | grep libmad ``` --- ### **典型报错及处理** ```bash # 案例1: "File exists" ln: failed to create symbolic link '/usr/lib64/libmad.so.0': File exists ➜ 解决方案:删除旧链接后重试 # 案例2: "No such file or directory" ln: failed to access '/usr/lib64/libmad.so.0.2.1': No such file or directory ➜ 解决方案:重新安装 libmad 或修正版本号 # 案例3: "Permission denied" ln: failed to create symbolic link '/usr/lib64/libmad.so.0': Permission denied ➜ 解决方案:使用 `sudo -i` 进入 root shell 再执行 ``` --- ### **补充说明:符号链接的作用** ```mermaid graph LR A[应用程序 sox] -->|运行时请求| B[libmad.so.0] B -->|实际指向| C[libmad.so.0.2.1] ``` - **主版本号约定**:`libmad.so.0` 表示 API 兼容的主版本,`0.2.1` 是具体实现版本 - **ABI 兼容性**:保持主版本号不变可确保二进制兼容性 --- ### **替代方案** 若问题持续存在,可直接修改 `ld.so.conf`: ```bash # 添加库路径到配置 echo "/usr/local/lib" | sudo tee /etc/ld.so.conf.d/custom.conf sudo ldconfig ``` --- 通过以上步骤,99% 的符号链接问题可被解决。如果仍报错,请提供以下信息: ```bash # 执行并反馈结果 ls -l /usr/lib64/libmad* rpm -q libmad file /usr/lib64/libmad.so.0.2.1 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值