原创文章,转载请注明: 转载自工学1号馆
这篇文将将继续介绍Hadoop作业的提交,主要剖析执行shell命令的内部机制
假设用户采用java语言编写了一个MapReduce程序,并将其打包成XXX.jar,然后通过以下命令提交作业:
$HADOOP_HOME/bin/hadoop jar example.jar \ -D mapred.job.name=”example” \ -D mapred.reduce.tasks=2 \ -files=blacklist.txt,whitelist.txt \ -libjars=third-party.jar \ -archives=dictionary.zip \ -input /test/input \ -output /test/output
当用户输入以上命令后,bin/hadoop脚本根据“jar”命令将作业交给RunJar类处理,相关代码如下:
…… elif [ "$COMMAND" = "jar" ] ; then CLASS=org.apache.hadoop.util.RunJar ……
下面来详细剖析RunJar类源代码:
RunJar类中只有一个函数:unJar,作用是将一个jar包解压缩成一个目录
public static void unJar(File jarFile, File toDir) throws IOException { JarFile jar = new JarFile(jarFile); try { Enumeration entries = jar.entries(); while (entries.hasMoreElements()) { JarEntry entry = (JarEntry)entries.nextElement(); if (!entry.isDirectory()) { InputStream in = jar.getInputStream(entry); try { File file = new File(toDir, entry.getName()); if (!file.getParentFile().mkdirs()) { if (!file.getParentFile().isDirectory()) { throw new IOException("Mkdirs failed to create " + file.getParentFile().toString()); } } OutputStream out = new FileOutputStream(file); try { byte[] buffer = new byte[8192]; int i; while ((i = in.read(buffer)) != -1) { out.write(buffer, 0, i); } } finally { out.close(); } } finally { in.close(); } } } } finally { jar.close(); } }
需了解的知识:
JarFile类:用于从任何可以使用 java.io.RandomAccessFile
打开的文件中读取 jar 文件的内容。它扩展了 java.util.zip.ZipFile
类,使之支持读取可选的 Manifest
条目。Manifest
可用于指定关于 jar 文件及其条目的元信息。
public Enumeration<JarEntry> entries():返回 zip 文件条目的枚举。
-
JarEntry类:此类用于表示 JAR 文件条目。
理论了半天,来做个实验,在eclipse上建立一个java类来模拟一下。由于使用的都是java库文件,所以不需要配置hadoop运行环境,十分方便
import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Enumeration; import java.util.jar.*; public class UnjarTest { public static void unJar(File jarFile, File toDir) throws IOException { JarFile jar = new JarFile(jarFile); //创建一个jar包文件对象 int j = 0; try { Enumeration entries = jar.entries(); //返回 zip 文件条目的枚举 while (entries.hasMoreElements()) { //条目枚举对象非空 JarEntry entry = (JarEntry)entries.nextElement(); //将条目的枚举强制转换为Jar文件条目 if (!entry.isDirectory()) { InputStream in = jar.getInputStream(entry); try { File file = new File(toDir, entry.getName()); if (!file.getParentFile().mkdirs()) { if (!file.getParentFile().isDirectory()) { throw new IOException("Mkdirs failed to create " + file.getParentFile().toString()); } } OutputStream out = new FileOutputStream(file); try { byte[] buffer = new byte[8192]; int i; while ((i = in.read(buffer)) != -1) { out.write(buffer, 0, i); // System.out.println(i); j++; } // System.out.println("------------------------"); System.out.println(buffer); } finally { out.close(); } } finally { in.close(); } }//endif } } finally { System.out.println(j); jar.close(); } } public static void main(String[] args) { File fromFile = new File("F:\\workspace\\jar\\hadoop-examples-1.0.1.jar"); File toFile = new File("F:\\workspace\\jar"); try { unJar(fromFile, toFile); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
我这里使用的是hadoop自带的examples的jar包来做实验,输入输出目录指定后,即可运行程序,结果如预期的一样,将hadoop-examples-1.0.1.jar包解压缩到指定的目录
RunJar类中的main函数解压jar包和设置环境变量,将运行参数传递给MapReduce程序,并运行之。
Comments