Hadoop执行jar文件流程分析

利用./bin/hadoop脚本执行jar文件是执行Hadoop自带测试包hadoop-test-version.jar和hadoop-example-version.jar的标准方法,当然用户开发的程序也需要用这种方法在hadoop中执行。本文以执行pi计算方法为例,详细分析Hadoop执行jar文件的流程。所用到的命令例子如下:

   ./bin/hadoopjar hadoop-examples-1.1.2.jar pi 100 100

涉及到的原文件列表如下:

   ./bin/hadoop
   ./src/core/org/apache/hadoop/util/RunJar.java
   ./src/examples/org/apache/hadoop/examples/ExampleDriver.java
   ./src/core/org/apache/hadoop/util/ProgramDriver.java

1. bin/hadoop脚本执行流程

Hadoop的脚本文件.bin/hadoop是Hadoop最终要的脚本,是绝大多数hadoop命令的入口。通过分析该脚本源代码,可知它的执行流程主要如下:

(1)、获得用户命令COMMAND,本例是jar。
(2)、设置JAVA_HOME,JAVA_HEAP_SIZE等变量。
(3)、搜索诸如./build/class等目录,设置类路径CLASSPATH。
(4)、设置诸如HADOOP_LOG_DIR,HADOOP_LOGFILE等变量。
(5)、根据COMMAND的内容,确定需要加载执行的类CLASS和java参数HADOOP_OPTS,如COMMAND为jar时,CLASS=org.apache.hadoop.util.RunJarl。
(6)、设置库路径JAVA_LIBRARY_PATH,主要是加载本地库路径。
(7)、根据前6步设置的变量和得到的类信息,调用java执行类(RunJar)。

2. org.apache.hadoop.util.RunJar执行流程

./bin/hadoop调用java命令加载执行RunJar类后,执行流程到达RunJar类的main函数,其主要内容如下(为突出重点,源代码化简如下):

publics tatic void main(String[] args) throws Throwable {
    String fileName = args[firstArg++];
    Filefile = new File(fileName);
    JarFile jarFile = newJarFile(fileName);
    Manifest manifest = jarFile.getManifest();
    if (manifest != null){
        mainClassName = manifest.getMainAttributes().getValue("Main-Class");
    }
    mainClassName = mainClassName.replaceAll("/",".");


    FiletmpDir = new File(newConfiguration().get("hadoop.tmp.dir"));
    tmpDir.mkdirs();
    final File workDir = File.createTempFile("hadoop-unjar","",tmpDir);
    workDir.mkdirs();


    unJar(file,workDir);

    ArrayList<URL>classPath = newArrayList<URL>();
    ClassLoaderloader = new URLClassLoader(classPath.toArray(newURL[0]));
    Thread.currentThread().setContextClassLoader(loader);


    Class<?> mainClass = Class.forName(mainClassName,true,loader);
    Methodmain = mainClass.getMethod("main",newClass[] {
                    Array.newInstance(String.class,0).getClass()});
    String[]newArgs = Arrays.asList(args).subList(firstArg,args.length).toArray(newString[0]);
    main.invoke(null,new Object[] { newArgs });
}

RunJar的main函数主要流程如下:

(1)、根据用户命令行参数首先得到jar文件的文件名,本里为hadoop-examples-1.1.2.jar,然后 通过文件清单Manifest得到jar的主类Main-Class,通过查看该jar文件的META-INFO/MANIFEST.MF得知,jar文件的主类为org/apache/hadoop/examples/ExampleDriver。
(2)、准备运行环境,在配置的系统路径hadoop.tmp.dir下创建hadoop-unjar*目录,作为作业执行的工作目录;然后调用unjar方法把jar文件解压到该目录下,unjar方法比较简单,在此不作分析。
(3)、利用java反射机制和主类类名ExampleDriver得到运行时类mainClass,进而得到类的main方法,最后准备命令行参数,调用main.invoke执行ExampleDriver的main方法。

3.org.apache.hadoop.examples.ExampleDriver执行流程

RunJar利用java反射机制执行ExampleDriver的main方法,该方法源代码如下:

public static void main(String argv[]){
       ProgramDriver pgd = new ProgramDriver();
       pgd.addClass("word count",WordCount.class,
                   "A map/reduce program that counts the words in the input files.");
       ... 
       pgd.driver(argv);
   }

该方法主要定义一个Programriver变量pgd,然后添加各种example的类和描述信息,然后调用pgd.driver(argv)方法执行对应example的类。

4. org/apache/hadoop/util/ProgramDriver分析

该类有一个内部类ProgramDescription,用来描述一个example类的相关信息;成员变量main表示example类的main方法,description是该exmaple类的简单描述。该内部类的invoke方法使用java反射机制执行example类的main方法。
ProgramDriver类的成员变量programs记录了当前example类的映射集合,成员方法addClass用以把新的example类添加到programs中。方法driver(argv)查中programs得到argv[0]对应的ProgramDescription对象,然后调用该对象的invoke方法执行该example类的main方法。

5. 总结

Hadoop通过功能强大的./bin/hadoop脚本实现了其绝大多数命令行接口。本文主要分析了hadoop执行jar文件的流程:通过解析jar文件的到主类,利用java反射机制执行主类的main方法,进而执行相关example类。这些example类是典型的mapreduce作业,对这些作业的分析和hadoopmapred框架加载执行这些作业,将在以后的学习中逐步分析。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值