hadoop jar分析,hadoopjar
在hadoop集群中经常用hadoop jar向hadoop集群提交jar包运行分布式程序。
这里hadoop是$HADOOP_HOME/bin目录下的一个核心脚本,也是hadoop集群所有启动脚本的核心脚本,这个脚本最重要的就是把Hadoop依赖的库$HADOOP_HOME/share和配置文件目录$HADOOP_HOME/etc/hadoop给加到CLASSPATH中,可以用hadoop classpath命令查看。这里我们要关心的就是"$COMMAND" = "jar"时(也就是hadoop jar命令)对应的类org.apache.hadoop.util.RunJar,下面分析一下这个。
RunJar是Hadoop中的一个工具类,结构很简单,只有两个方法:main和unJar。我们从main开始一步步分析。
main首先检查传递参数是否符合要求,然后从第一个传递参数中获取jar包的名字,并试图从jar中包中获取manifest信息,以查找mainclass name。如果查找不到mainclass name,则把传递参数中的第二个设为mainclass name。当打的jar是runnable jar时,jar包中包含manifest信息,不需要指定mainclass name,当是一般jar包时,必须指定主类。
接下去,就是在"hadoop.tmp.dir"下创建一个临时文件夹,并挂载上关闭删除线程。这个临时文件夹用来放置解压后的jar包内容。jar包的解压工作由unJar方法完成,通过JarEntry逐个获取jar包内的内容,包括文件夹和文件,然后释放到临时文件夹中。
解压完毕后,开始做classpath的添加,依次把解压临时文件夹、传递进来的jar包、临时文件夹内的classes文件夹和lib里的所有jar包加入到classpath中。接着以这个classpath为搜索URL新建了一个URLClassLoader(要注意这个类加载器的parent包括了刚才bin/hadoop脚本提交时给的classpath),并设置为当前线程的上下文类加载器。
最后,利用Class.forName方法,以刚才的那个URLClassLoader为类加载器,动态生成一个mainclass的Class对象,并获取它的main方法,然后以传递参数中剩下的参数作为调用参数来调用这个main方法(常用的参数是文件输入路径和输出路径)。
总结来说这个RunJar类是一个很简单的类,就是解压传递进来的jar包,再添加一些classpath,然后动态调用jar包里的mainclass的main方法。
经常在mapreduce程序中看到这样的代码:Configuration conf=new Configuration();
Job job=Job.getInstance(conf);
或者在hdfs相关的代码中: Configuration conf=new Configuration();
FileSystem.get(conf);
这里的Configuration类初始化时会读取classpath下的配置文件,如果没有的话则会读取classpath下jar包中默认的配置文件,常用的配置文件有core-site.xml、hdfs-site.xml、mapred-site.xml、yarn-site.xml等。当然Configuration类也有许多set方法显示的设置各个参数。
综上所述:1、用hadoop jar命令,已经把配置文件和依赖的jar包加入到classpath中。根据hadoop脚本的原理,也可以使用java -jar命令启动分布式程序,此时需要把配置文件加在classpath下,并调用job.setJar方法(此时调用setJarByClass方法会找不到jar包,同样hadoop jar命令如果后面跟的是runnable jar,setJarByClasee方法也会找不到jar,必须使用setJar方法),并export成runnable jar,因为runnable jar会把classpath中的jar包和配置文件都打进去。
2、在elcipse中如果classpath下没有配置文件,默认的执行模式是本地模式。
3、原理上也可以在windows下的eclipse中直接启动一个客户端提交分布式程序,但是由于windows平台和linux平台的不兼容(主要是变量的表示方法,windows是%%,linux是$,和文件路径的表示),windows客户端下生成的启动rmappmaster的脚本,提交到resource manager时不能识别。此时可以修改源码中yarnrunner类的实现,将此脚本修改成linux下的版本就可以了 。
4、eclipse有一个插件,也可以实现windows下提交,待补充
5、补充java -jar和java -cp的区别:java -jar 执行runnable jar ,不能添加classpath,不必指定主类;java -cp执行一般jar包,可以设置classpath,必须指定主类。