大数据框架hadoop之版本显示的实现逻辑
版本显示在各个项目或系统中都有使用到,实现方式也各式各样,接下来了解一下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;
页:
[1]