Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Mapreduce 任务提交源码分析1

Mapreduce 任务提交源码分析1

作者头像
囚兔
发布于 2018-02-08 03:03:41
发布于 2018-02-08 03:03:41
1.1K00
代码可运行
举报
文章被收录于专栏:IT杂记IT杂记
运行总次数:0
代码可运行

提交过程

一般我们mapreduce任务是通过如下命令进行提交的

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
$HADOOP_HOME/bin/hadoop jar $MR_JAR $MAIN_CLASS

hadoop脚本中有如下代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    elif [ "$COMMAND" = "jar" ] ; then
      CLASS=org.apache.hadoop.util.RunJar

//... 略
    exec "$JAVA" $JAVA_HEAP_MAX $HADOOP_OPTS $CLASS "$@"

可以看到hadoop命令提交mapreduce其实就是执行了org.apache.hadoop.util.RunJar类的main方法,接下来我们来看下这个main方法,只关注最核心的逻辑,其他不重要的部分略去。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static void main(String[] args) throws Throwable {
  String usage = "RunJar jarFile [mainClass] args...";
  // 第一个参数是jar文件路径,第二个参数是主类名(可选),后续跟其他参数
  // ...
  

  int firstArg = 0;
  String fileName = args[firstArg++];
  File file = new File(fileName);
  // 构建jar文件对象
  // ...

  // --: 这部分逻辑是获取主类名
  //     优先从jar文件的Manifest信息中获取主类名; (只有当打包jar时采用可运行的jar文件的方式才有这个信息,否则普通的jar文件中不包含该信息)
  //     如果无法获取到,则采用第二参数值作为主类名;
  // ---------------------------------------------------------------------------
  String mainClassName = null;

  JarFile jarFile;
  try {
    jarFile = new JarFile(fileName);
  } catch(IOException io) {
    throw new IOException("Error opening job jar: " + fileName)
      .initCause(io);
  }

  Manifest manifest = jarFile.getManifest();
  if (manifest != null) {
    mainClassName = manifest.getMainAttributes().getValue("Main-Class");
  }
  jarFile.close();

  if (mainClassName == null) {
    if (args.length < 2) {
      System.err.println(usage);
      System.exit(-1);
    }
    mainClassName = args[firstArg++];
  }
  mainClassName = mainClassName.replaceAll("/", ".");
  // ---------------------------------------------------------------------------

  // 获取Hadoop临时目录,指的是本地操作系统的一个目录
  // hadoop.tmp.dir配置可在core-site.xml配置文件中配置
  File tmpDir = new File(new Configuration().get("hadoop.tmp.dir"));
  ensureDirectory(tmpDir);

  // --:为这个任务在临时目录下面创建一个临时的工作目录,目录名的格式为:“hadoop-unjar + Long型随机数”
  //------------------------------------------------------------------------------
  final File workDir;
  try { 
    workDir = File.createTempFile("hadoop-unjar", "", tmpDir);
  } catch (IOException ioe) {
    System.err.println("Error creating temp dir in hadoop.tmp.dir "
                       + tmpDir + " due to " + ioe.getMessage());
    System.exit(-1);
    return;
  }

  if (!workDir.delete()) {
    System.err.println("Delete failed for " + workDir);
    System.exit(-1);
  }
  ensureDirectory(workDir);
  //------------------------------------------------------------------------------

  // 为Java进程添加一个钩子程序,当程序shutdown时清楚临时工作目录
  ShutdownHookManager.get().addShutdownHook(
    new Runnable() {
      @Override
      public void run() {
        FileUtil.fullyDelete(workDir);
      }
    }, SHUTDOWN_HOOK_PRIORITY);

  // 将jar文件里面的内容解压到这个临时的工作目录
  unJar(file, workDir);

  // -- 将:
  // workDir/, workDir/classes/, workDir/lib/${allfiles} 添加到classpath
  //------------------------------------------------------------------------------
  ArrayList<URL> classPath = new ArrayList<URL>();
  classPath.add(new File(workDir+"/").toURI().toURL());
  classPath.add(file.toURI().toURL());
  classPath.add(new File(workDir, "classes/").toURI().toURL());
  File[] libs = new File(workDir, "lib").listFiles();
  if (libs != null) {
    for (int i = 0; i < libs.length; i++) {
      classPath.add(libs[i].toURI().toURL());
    }
  }
  //------------------------------------------------------------------------------
  

  // --: 以上面的classpath创建一个URLClassLoader,作为主线程的classLoader
  ClassLoader loader =
    new URLClassLoader(classPath.toArray(new URL[0]));
  Thread.currentThread().setContextClassLoader(loader);

  // --:通过反射的机制去调用主类的main方法,并将除jar文件和[mainClass]以外的所有参数传递给该main方法
  Class<?> mainClass = Class.forName(mainClassName, true, loader);
  Method main = mainClass.getMethod("main", new Class[] {
    Array.newInstance(String.class, 0).getClass()
  });
  String[] newArgs = Arrays.asList(args)
    .subList(firstArg, args.length).toArray(new String[0]);
  try {
    main.invoke(null, new Object[] { newArgs });
  } catch (InvocationTargetException e) {
    throw e.getTargetException();
  }
}

总结

hadoop命令做的事情就是将jar文件的内容解压到临时工作目录,并将解压后的workDir/, workDir/classes/, workDir/lib/${allfiles} 一系列路径加入到自定义的ClassLoader中,并通过反射的机制去执行jar文件中Manifest中的主类或是用户指定的主类。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
springboot的jar为何能独立运行
在开发springboot应用时,通过java -jar命令启动应用是常用的方式,今天就来一起了解这个简单操作背后的技术;
程序员欣宸
2021/05/13
7630
springboot的jar为何能独立运行
大数据学习之路04——使用IDEA开发MapReduce程序
这里以Hadoop的官方示例程序WordCount为例,演示如何一步步编写程序直到运行。
汪志宾
2019/05/24
2.3K0
大数据学习之路04——使用IDEA开发MapReduce程序
SpringBoot的启动引导类真的是XXApplication吗?
SpringBoot项目中的启动类,一般都是XXApplication,例如StatsApplication,UnionApplication。每个项目的启动类名称都不一样。但是它的启动类真的是XXApplication吗?
温安适
2020/06/07
1.3K0
为什么SpringBoot的 jar 可以直接运行?
SpringBoot提供了一个插件spring-boot-maven-plugin用于把程序打包成一个可执行的jar包。在pom文件里加入这个插件即可:
JAVA葵花宝典
2020/04/23
1.2K0
SpringBoot项目jar、war包启动解析
war包启动:需要先启动外部的Web服务器,实现Servlet3.0规范中引导应用启动类,然后将war包放入Web服务器下,Web服务器通过回调引导应用启动类方法启动应用。
阿珍
2023/03/20
2K0
eclipse中hadoop2.3.0环境部署及在eclipse中直接提交mapreduce任务
1 eclipse中hadoop环境部署概览 eclipse中部署hadoop包括两大部分:hdfs环境部署和mapreduce任务执行环境部署。一般hdfs环境部署比较简单,部署后就 可以在eclipse中像操作windows目录一样操作hdfs文件。而mapreduce任务执行环境的部署就比较复杂一点,不同版本对环境的要求度 高低不同就导致部署的复杂度大相径庭。例如hadoop1包括以前的版本部署就比较简单,可在windows和Linux执行部署运行,而hadoop2 及以上版本对环境要求就比较严格
闵开慧
2018/04/02
1.1K0
eclipse中hadoop2.3.0环境部署及在eclipse中直接提交mapreduce任务
spring boot应用启动原理分析
摘要: spring boot quick start 在spring boot里,很吸引人的一个特性是可以直接把应用打包成为一个jar/war,然后这个jar/war是可以直接启动的,不需要另外配置一个Web Server。
Java架构师历程
2018/09/26
1.9K0
硬核艿艿,新鲜出炉,直接带你弄懂 Spring Boot Jar 启动原理!
Spring Boot 提供了 Maven 插件 spring-boot-maven-plugin,可以方便的将 Spring Boot 项目打成 jar 包或者 war 包。
芋道源码
2020/06/05
2K0
JMeter5.1启动类NewDriver源代码分析
启动JMeter,主要通过NewDriver来实现,直接用于本地 GUI 和非 GUI 调用。
天堂小说
2021/12/03
4920
SpringBoot - 探究Spring Boot应用是如何通过java -jar 启动的
大家开发的基于Spring Boot 的应用 ,jar形式, 发布的时候,绝大部分都是使用java -jar 启动。 得益于Spring Boot 的封装 , 再也不用操心搭建tomcat等相关web容器le , 一切变得非常美好, 那SpringBoot是怎么做到的呢?
小小工匠
2021/08/17
1.5K0
SpringBoot - 探究Spring Boot应用是如何通过java -jar 启动的
SpringBoot打包部署解析:Launcher实现原理
Launcher实现原理 在上节内容中,我们得知 jar 包 Main-Class 指定入口程序为 Spring Boot 提供的 L auncher(JarL auncher),并不是我们在 Sp
愿天堂没有BUG
2022/10/28
1K0
SpringBoot打包部署解析:Launcher实现原理
SpringBoot系列-- jar可执行原理
文章篇幅较长,但是包含了SpringBoot 可执行jar包从头到尾的原理,请读者耐心观看。
田维常
2020/02/13
9400
探秘Java:从main函数启动开始
  不知道在座的各位朋友是否跟我一样,初学Java时写下的第一段代码就是类似下面这段代码:
闲宇非鱼
2022/02/08
1.4K0
探秘Java:从main函数启动开始
本地idea开发mapreduce程序提交到远程hadoop集群执行
通过idea开发mapreduce程序并直接run,提交到远程hadoop集群执行mapreduce。
王小雷
2019/05/29
1.9K1
通过Java程序提交通用Mapreduce任务并获取Job信息
背景 我们的一个业务须要有对MR任务的提交和状态跟踪的功能,须要通过Java代码提交一个通用的MR任务(包括mr的jar、配置文件、依赖的第三方jar包),并且须要在提交后跟踪其状态和历史,所以在提交后程序须要拿到改提交的MR的JobID。 解决方案 首先 可以想到的是通过  ${HADOOP_HOME}/bin/hadoop jar 命令来提交,并从命令执行的标准输出中取到jobID,这样确实可以解决,但是这样做有几个问题: 须要通过Java程序去启动一个子进程,并且要监控它的标准输出,性能不会很好,有点
囚兔
2018/02/08
2.4K1
通过Java程序提交通用Mapreduce任务并获取Job信息
通过Java程序提交通用Mapreduce无法回收类的问题
问题描述 上次发布的博客 通过Java程序提交通用Mapreduce,在实施过程中发现,每次提交一次Mapreduce任务,JVM无法回收过程中产生的MapReduceClassLoader对象以及其生成的类。 通过定制如下代码来实现多次任务提交测试: public class JobSubmitTest { public static void submit(String classPath, String mainClassName) { ClassLoader originC
囚兔
2018/03/29
1.1K1
通过Java程序提交通用Mapreduce无法回收类的问题
记Hadoop MapReduce入门学习
在之前的文章记hadoop伪分布式安装中,我们已经成功地安装了Hadoop,并且在文章在java中通过API读写hdfs入门学习中实现了通过java代码访问hdfs文件系统,接下来就进入到了MapReduce的学习。
zhangheng
2021/02/25
7590
Spark提交任务入口源码分析
我们平常在使用Spark进行提交代码的时候,一般是直接在装有spark客户端的机器上提交jar包执行。运行命令如下:
幽鸿
2020/03/30
7210
Linux巩固记录(5) hadoop 2.7.4下自己编译代码并运行MapReduce程序
程序代码为 ~\hadoop-2.7.4\share\hadoop\mapreduce\sources\hadoop-mapreduce-examples-2.7.4-sources\org\apache\hadoop\examples\WordCount.java  
肖哥哥
2018/08/02
4020
tomcat无法正常关闭问题分析及解决
这时我们就只能通过强制杀死进程的方式停止Tomcat了:kill -9 <tomcat_process_id>。 那么,为什么使用shutdown.sh无法正常停止Tomcat进程呢?
编程随笔
2019/09/11
2.3K0
tomcat无法正常关闭问题分析及解决
推荐阅读
相关推荐
springboot的jar为何能独立运行
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验