一个面试题--类路径中存在多个版本不同的jar包会有冲突吗

一个面试题:classpath中同时存在不同版本jar包(如slf4j-log4j12-1.5.8.jar, slf4j-log4j12-1.7.12.jar), 会有冲突吗?

创建一个工程Test1, 其中有一个类: com.test.Test

创建另一个工程Test2, 其中也有同名类: com.test.Test

而两个工程中的com.test.Test的内容都是一样的(除了sysout中的工程名外),如下所示:

public class Test {
	public void doSomething(){
		System.out.println("do something in test2 project");
		System.out.println("classload is: "+this.getClass().getClassLoader());
	}
}

将它们两个打成jar包,均导入到第三个工程Test3中(模拟版本冲突的情况),如下所示:

121923_k42F_1175066.png

在这第三个工程中,有这么一个测试类,如下所示:

public class ClassLoadTest {

	public static void main(String[] args) {
		Test test = new Test();
		test.doSomething();
	}

}

main方法中引用了test1.jar和test2.jar中都存在的com.test.Test, 编译没有报错, 运行会报错吗? 如提示存在多个com.test.Test.

运行结果如下:

$ java ClassLoadTest
do something in test2 project
classload is: sun.misc.Launcher$AppClassLoader@7451b0a

一切正常,并没有报错。即类路径中存在不同版本的jar包并不会导致冲突。看一下运行该main方法时的完整类加载过程,

$ java -XX:+TraceClassLoading ClassLoadTest
[Opened /usr/lib/jvm/java-7-openjdk-amd64/jre/lib/rt.jar]
[Loaded java.lang.Object from /usr/lib/jvm/java-7-openjdk-amd64/jre/lib/rt.jar]
[Loaded java.io.Serializable from /usr/lib/jvm/java-7-openjdk-amd64/jre/lib/rt.jar]
......
[Loaded com.test.Test from file:/home/zhuguowei/workspace/temp-use/lib/test2.jar]
...

似乎会随机加载一个存在com.test.Test类的jar包。

又经过实验发现类路径中谁在前, 就会加载哪个,如下所示:

#终端一
$ export CLASSPATH=$CLASSPATH:/lib/test1.jar:/lib/test2.jar
$ java com.zhugw.study.ClassLoadTest
do something in test1 project
classload is: sun.misc.Launcher$AppClassLoader@ecfeb11

#开启一个新的终端
$ export CLASSPATH=$CLASSPATH:/lib/test2.jar:/lib/test1.jar
$ java com.zhugw.study.ClassLoadTest
do something in test2 project
classload is: sun.misc.Launcher$AppClassLoader@6a3449a8

但若同样全限定名的类中的某些方法参数不同的话,或其中一个多了一些或少了一些方法的话, 都会产生一些问题, 如Test1工程中的com.test.Test中,存在如下的一个方法:

public void doAnotherthing(String foo){
	System.out.println("do another thing in test1 project");
}

而在Test2工程中的com.test.Test中同样名称的方法多了一个参数, 

public void doAnotherthing(String foo, String bar){
	System.out.println("do another thing in test2 project");
}

这时Test3中的测试类的代码如下所示:

Test test = new Test();
test.doSomething();

test.doAnotherthing("foo"); //注:调用的是test1.jar中单参的doAnotherthing

没有编译错误,但运行时就有问题了,如下所示:

$ export CLASSPATH=$CLASSPATH:/lib/*
$ java ClassLoadTest
do something in test2 project
classload is: sun.misc.Launcher$AppClassLoader@7451b0af
Exception in thread "main" java.lang.NoSuchMethodError: com.test.Test.doAnotherthing(Ljava/lang/String;)V
	at com.zhugw.study.ClassLoadTest.main(ClassLoadTest.java:14)

因为此时加载的是test2.jar。但是通过如下方式引入jar包就没有问题:

$ export CLASSPATH=$CLASSPATH:/lib/test1.jar:/lib/test2.jar
$ java com.zhugw.study.ClassLoadTest
do something in test1 project
classload is: sun.misc.Launcher$AppClassLoader@6a3449a8
do another thing in test1 project

此时加载的是test1.jar。


转载于:https://my.oschina.net/zhuguowei/blog/465964

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值