记录一个类加载变量引发的问题

本文介绍了解决在WebLogic环境下启动服务时,因类加载变量导致配置文件读取失败的问题。通过将配置文件放置于服务器配置路径,并修改setDomainEnv.sh脚本,成功实现了启动时正确读取配置。

类加载变量导致的问题

类加载变量导致的问题

因为项目需要,银行要求使用weblogic部署并且启动所有项目,不允许项目单独开服务启动一般都有这样的要求,我所在的项目组有两个单独main方法启动的服务,经过改造变成了可以部署在weblogic启动的web服务,其中一个网关接口服务,依赖于银行方提供的总线ESB服务,发送接口实现和其他系统交互,这中间存在需要行方提供的esb.jar这个jar包,以及行方提供的esbclient.properties配置文件。

  • 如下是行方提供的jar文件java类读取esbclient.properties事例代码
public class ClientEngine{
	private static String envProperties = "esbclient.properties";
	private static String envProperties = "mssterkey.properties";
	private static String clientPath = "esb.client.path";
	...
	static{
		String path = System.getProperty(clientPath);
		if(log.isDebugEnabled()){
			log.debug(clientPath + "=" + path);
		}
		if((path != null)&&(!path.equals(""))){
			File f = new File(path + File.separator + envProperties);
			...
		}
	}
}
  • esbclient.properties是个文件,里面定义的参数也是类似client.protocol=HTTP
    这种,上面这段代码就带来一个问题,读取配置文件的是先读取path,也就是根据我们指定的clientPath去找到esbclient.properties,然后再去读取properties文件里面的配置项,但是因为这个读取的配置是写在static块里面的,这个就需要我们一启动weblogic就需要把clientPath这个指定的esb.client.path传进去,不然永远无法取到这个值。

找到问题根源,接下来就是如何解决它,其实很简单,只需要将这两个配置文件放置到服务器配置文件路径,在weblogic启动的bin目录下,有个配置文件叫setDomainEnv.sh的脚本,要解决这个启动的时候就传递这个path进去只需要把这个参数当作JVM的参数传入就行,但这个不是classLoader动态加载的所以只能给死路径,所以只需要写**-Desb.client.path=/wls/config**。然后这个路径存放这两个配置文件,启动weblogic,可以在nohup文件开头看到这个参数被当作JVM的参数传入了,问题得到解决。

转载请注明出处!

<think> 嗯,用户这次的问题是关于动态库加载冲突的,具体场景是工程中加载两个包含相同的动态库是否会有问题。用户之前似乎研究过动态库的链接机制,从引用内容看,ta对链接器行为和资源ID冲突有一定了解。 用户可能正在开发一个复杂项目,遇到了动态库冲突问题。ta的引用内容显示已经注意到两个关键点:一是资源ID冲突(对话框示例),二是动态库链接时的符号查找机制。这说明用户有底层技术背景,问题提得很专业。 从技术角度看,这个问题需要分三层分析: 首先是符号冲突层面。名本质上是全局符号,当两个动态库导同名时,链接器默认行为是采用“先到先得”策略。这里要注意用户提到的“相同”可能存在歧义——是指完全同名的,还是同名且同实现的?如果是后者问题更严重。 其次是动态加载机制。Linux的dlopen默认使用RTLD_LAZY模式,首次调用时才解析符号。当主程序同时依赖两个库的同名时,实际加载顺序取决于依赖树,可能产生非确定性结果。特别要注意用户引用中提到的“编译时只记录文件名不记录路径”这个细节,这会导致运行时依赖查找的不确定性。 最后是内存隔离问题。最危险的场景是两个动态库的定义不同但名相同。这种情况下,同一个名在不同库中对应不同内存布局,任何跨库的对象传递都会导致内存越界。即使用dynamic_cast也无效,因为型信息在各自库中独立注册。 用户可能没意识到的是:这种冲突在Windows平台更危险,因为DLL没有RTLD_LOCAL等效机制。而Linux通过dlopen的flag可以部分隔离符号表,但C++的RTTI机制仍可能穿透隔离。 需要特别提醒用户检查两个点:一是是否真的完全相同(包括虚函数表顺序),二是是否使用了工厂模式等隔离机制。从ta引用对话框资源ID冲突的例子看,用户可能已经遇到问题,只是尚未关联到定义冲突上。 </think>在工程中加载两个包含**同名**的动态库会导致严重冲突,具体问题如下: --- ### 核心问题:符号冲突(Symbol Collision) 1. **全局符号表污染** 动态库加载时,其导名称会写入**全局符号表**。若两个库包含同名: - 链接器或加载器无法区分同名属于哪个库 - 实际加载的定义取决于库的加载顺序(不确定性) - 示例:若 `LibA.so` 和 `LibB.so` 均包含 `MyClass`,调用 `new MyClass()` 可能随机指向任一实现 2. **内存布局不一致** 即使两个的名称相同,若实现不同(成员变量/虚函数表差异): ```cpp // LibA.so class MyClass { int a; virtual void foo(); }; // LibB.so class MyClass { float b; virtual void bar(); }; ``` - 跨库传递对象时,因内存布局不同导致**内存越界访问**或**虚表指针错误** - 引发段错误(Segmentation Fault)或未定义行为(UB) --- ### 根本原因:动态链接机制 1. **符号解析规则** - 动态链接器(如 `ld-linux.so`)按加载顺序填充全局符号表 - 后加载库的同名符号会**覆盖**先加载的符号(依赖 `LD_PRELOAD` 等机制) 2. **编译期与运行期分离** - 编译期:仅检查符号是否存在(如用户引用[2]所述) - 运行期:动态加载器按默认路径(如 `/usr/lib`)或 `LD_LIBRARY_PATH` 查找库,**不验证实现一致性** --- ### 冲突场景验证 | 场景 | 结果 | |---------------------|--------------------------| | 两个库的同名实现相同 | 可能正常工作(但仍有风险)| | 两个库的同名实现不同 | **必然崩溃或数据损坏** | | 主程序显式调用特定库 | 仍可能因全局符号覆盖失败 | --- ### 解决方案 1. **命名空间隔离** 为每个库的添加独立命名空间: ```cpp // LibA.so namespace LibA { class MyClass; } // LibB.so namespace LibB { class MyClass; } ``` 2. **符号版本化(Symbol Versioning)** 使用GCC的 `.symver` 指令为符号添加版本后缀: ```bash g++ -shared -Wl,--version-script=mapfile ... ``` `mapfile` 内容示例: ```verilog LIB_A_1.0 { global: MyClass; local: *; }; ``` 3. **显式加载(dlopen)** 运行时通过 `RTLD_LOCAL` 隔离符号: ```cpp void* libA = dlopen("LibA.so", RTLD_LOCAL | RTLD_LAZY); void* libB = dlopen("LibB.so", RTLD_LOCAL | RTLD_LAZY); MyClass* (*createA)() = (MyClass*(*)())dlsym(libA, "createMyClass"); MyClass* objA = createA(); // 安全使用LibA的 ``` --- ### 关键总结 > ❗ **永远不要加载两个包含同名全局的动态库** > 即使实现相同,也无法保证: > 1. 不同编译选项导致内存布局差异(如调试版/发布版) > 2. 未来库升级引入不兼容变更 > > 必须通过**命名空间**或**符号隔离**主动规避冲突。 ---
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值