曾经在使用Storm时碰到一个问题:向集群提交一个新的Topology Jar包,在线运行的却是旧代码。自己百思不得其解,后来发现Storm的安装目录下(也可以说是Storm的HOME目录)有一个同名的旧Jar包,删除后问题解决。。。总结下自己的分析,请路过高手指正:
首先猜测问题出在Java CLASSPATH上,于是阅读Storm源代码去研究,终于在 bin/storm 这个可执行程序中找到原因。本质上, bin/storm是一个python脚本,它在执行时会把/home/test/storm-0.9.0.1/ 和 /home/test/storm-0.9.0.1/lib 两个目录下的所有jar包都加入CLASSPATH, 因而Storm在选择Topology Jar包源时,先选择了/home/test/storm-0.9.0.1/ 下的同名jar包,这个同名的旧jar包被copy到Nimbus的data目录,进而分发给supervisor。
解决问题后顺便温习Java CLASSPATH, 作为C程序员来总结下自己的理解:
为什么需要CLASSPATH?
Java编译器及虚拟机默认从当前目录寻找所依赖Java类的.class文件; 如果需要的.class文件不在当前目录,Java会从CLASSPATH所指定的目录中寻找.class文件。
JVM执行一个Java程序时,相当于动态加载;即只有当这个类被调用的时候,Java虚拟机才会载入它。CLASSPATH告诉Java虚拟机或者编译器,文件系统中哪些文件定义了要用到的类。
Java虚拟机按照下述流程来寻找和载入类:
<1> 系统导入类: Java平台内部的基础类,包括Java类库的公共类和为其服务的私有类。
<2> 扩展类:存在于JRE或者JDK扩展目录下的jar包,如jre/lib/ext/。 <3> 用户定义的包和类库
Linux下如何自己指定所依赖的jar包
$ java test.jar -cp /home/test/dependency.jar ===> 这种指定依赖的方式可以只对test.jar起作用,而不影响其他应用。