hadoop 执行 jar文件流程

./bin/hadoop脚本执行jar文件是执行Hadoop自带测试包hadoop-test-version.jarhadoop-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/hadoopHadoop最终要的脚本,是绝大多数hadoop命令的入口。通过分析该脚本源代码,可知它的执行流程主要如下:

   (1)、获得用户命令COMMAND,本例是jar

   (2)、设置JAVA_HOMEJAVA_HEAP_SIZE等变量。

   (3)、搜索诸如./build/class等目录,设置类路径CLASSPATH

   (4)、设置诸如HADOOP_LOG_DIR,HADOOP_LOGFILE等变量。

   (5)、根据COMMAND的内容,确定需要加载执行的类CLASSjava参数HADOOP_OPTS

           如COMMANDjar时,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("wordcount",WordCount.class,

                   "Amap/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、付费专栏及课程。

余额充值