大数据框架hadoop之版本显示的实现逻辑
使用场景
在bin目录下打印系统版本信息。
执行命令 |
结果 |
hadoop version |
|
结果显示,当前的hadoop版本为1.0.0。
接下来就一步步地跟踪代码,详细了解一下版本显示的实现逻辑。
Hadoop脚本
首先打开hadoop脚本(目录${HADOOP_HOME}/BIN),查看脚本接收到命令version后调用哪个类来处理。相关脚本如下:
... ... elif [ "$COMMAND" = "version" ] ; then CLASS=org.apache.hadoop.util.VersionInfo HADOOP_OPTS="$HADOOP_OPTS $HADOOP_CLIENT_OPTS" ... ... |
从上表可知,脚本接收到version命令后,对应的执行类是org.apache.hadoop.util.VersionInfo。
VersionInfo
运行时,对应的执行类VersionInfo在main中直接打印消息。相关代码如下:
/** * This class finds the package info for Hadoop and the HadoopVersionAnnotation * information. */ public class VersionInfo { private static Package myPackage; private static HadoopVersionAnnotation version; static { myPackage = HadoopVersionAnnotation.class.getPackage(); version = myPackage.getAnnotation(HadoopVersionAnnotation.class); } ... ... /** * 获取了HadoopVersionAnnotation实例的version()方法的返回值。 * @return the Hadoop version string, eg. "0.6.3-dev" */ public static String getVersion() { return version != null ? version.version() : "Unknown"; }
/** * Get the subversion revision number for the root directory * @return the revision number, eg. "451451" */ public static String getRevision() { return version != null ? version.revision() : "Unknown"; }
/** * 获取了HadoopVersionAnnotation实例的date()方法的返回值。 * @return the compilation date in unix date format */ public static String getDate() { return version != null ? version.date() : "Unknown"; }
/** * 获取了HadoopVersionAnnotation实例的user()方法的返回值。 * @return the username of the user */ public static String getUser() { return version != null ? version.user() : "Unknown"; }
/** * Get the subversion URL for the root Hadoop directory. */ public static String getUrl() { return version != null ? version.url() : "Unknown"; } ... ... public static void main(String[] args) { System.out.println("Hadoop " + getVersion()); System.out.println("Subversion " + getUrl() + " -r " + getRevision()); System.out.println("Compiled by " + getUser() + " on " + getDate()); } } |
定义了静态变量:myPackeage和version。其中version是HadoopVersionAnnotation的实例。 HadoopVersionAnnotation是Annotation接口类,在这里,hadoop项目组通过这种方式来获取系统版本信息。并不是直接写在代码中。
这个类是个比较普通的类,但是管理了Hadoop的版本信息,包括用户、编译时间、版本信息等内容。在这个类中,封装了HadoopVersionAnnotation这个注释类。
HadoopVersionAnnotation类
相关代码如下:
/** * A package attribute that captures the version of Hadoop that was compiled. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PACKAGE)//是对包的注释,很多地方都是用 public @interface HadoopVersionAnnotation {
/** * Get the Hadoop version * @return the version string "0.6.3-dev" */ String version();
/** * Get the username that compiled Hadoop. */ String user();
/** * Get the date when Hadoop was compiled. * @return the date in unix 'date' format */ String date();
/** * Get the url for the subversion repository. */ String url();
/** * Get the subversion revision. * @return the revision number as a string (eg. "451451") */ String revision(); } |
这只是个接口类,但是纵观整个项目工程,并没有找到实现类;查看整个项目的源码,也没有找到初始化的地方。
根据JDK语法,如果类型设置为PACKAGE,则需要在这个Annotation所在的包中,有一个package-info.java类,并且定义如下:
@HadoopVersionAnnotation(version="1.0.0-SNAPSHOT")
package org.apache.hadoop;
这样,在调用HadoopVersionAnnotation的version()方法时,才可以得到在package-info.java中对该方法的返回值。
下面,就要介绍这个package-info.java是怎么来的了。
package-info.java
查看编译后生成的hadoop-core-1.0.0.jar包,是可以看到package-info.class类的,相关信息如下:
|
由此可以推测,package-info类应该是在项目工程编译过程中生成的,接下来看一下build.xml文件,虽然没有package-info字眼,但确看到了version字眼,而且执行该脚本是在init目标下。如下所示:
<!-- ====================================================== --> <!-- Stuff needed by all targets --> <!-- ====================================================== --> <target name="init" depends="ivy-retrieve-common"> ... ... <exec executable="sh"> <arg line="src/saveVersion.sh ${version} ${build.dir}"/> </exec> ... ... </target> |
接下来将目光转移到saveVersion.sh脚本。
saveVersion.sh脚本
打开脚本saveVersion.sh,终于发现生成package-info.java类的源码了。相关脚本如下:
... ... mkdir -p $build_dir/src/org/apache/hadoop cat << EOF | \ sed -e "s/VERSION/$version/" -e "s/USER/$user/" -e "s/DATE/$date/" \ -e "s|URL|$url|" -e "s/REV/$revision/" \ > $build_dir/src/org/apache/hadoop/package-info.java /* * Generated by src/saveVersion.sh */ @HadoopVersionAnnotation(version="VERSION", revision="REV", user="USER", date="DATE", url="URL") package org.apache.hadoop; EOF |
打开hadoop编译时创建的目录,确实找到了package-info.java类,如下所示:
|
再打开package-info.java类,文件内容正是我们所期待的。如下所示:
/* * Generated by src/saveVersion.sh */ @HadoopVersionAnnotation(version="1.0.0", revision="", user="e40-nb2-pcmyuser", date="Mon Nov 17 14:40:26 2014", url="") package org.apache.hadoop; |
上一篇: 大众点评大数据 hadoop 应用案例