【Hadoop】Build and Execute

本文详细介绍了如何使用Eclipse导入Hadoop源码包,配置环境,编译源码,并通过Eclipse执行MapReduce程序。包括解决编译错误,配置classpath,使用MRUnit进行单元测试等步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Hadoop官方wiki上介绍了如何用Maven编译和生成Eclipse项目,但是它需要hadoop-common的trunk代码,因为只有trunk上有pom.xml文件。而对于其他release版本的源代码,都包含build.xml,因此可以通过ant来编译。本文根据自己的经验,总结一下如何将下载的tar.gz源码包导入Eclipse,进而通过Eclipse编译和执行Hadoop。

Compile and Build

  1. 从官网上下载源码包,这里下载的是hadoop-1.0.4.tar.gz,不需要解压
  2. 新建一个空的Eclipse Project,Import -> General -> Archive File,选择此tar.gz文件,将其全部导入新建的Project
  3. 将需要编译的源码package加入build path:Build Path -> Configure Build Path,这里加入core, examples, hdfs, mapred四个package。同时,将default output folder设置为build/classes (hadoop启动脚本默认将$HADOOP_HOME/build/classes加入classpath),如下图所示:
  4. 将lib目录下的所有jar文件加入Project Libraries,如下图所示:
  5. 接下来Eclipse将开始自动build,会发现很多编译错误。解决方法是下载一个jar文件,com.springsource.org.apache.tools.ant-1.8.1.jar,将其加入Project Library。

Execute

如果需要编写MapReduce程序,可以新建另一个Project,然后将Hadoop-1.0.4/build/classes目录加入Project Library。单元测试Mapper和Reducer可以使用MRUnit,测试代码如下所示:
	@Test
	public void testMap() {
		Text value = new Text("zhang jun");
		new MapDriver<Object, Text, Text, IntWritable>()
			.withMapper(new JunzWordCount.TokenizerMapper())
			.withInputValue(value)
			.withOutput(new Text("zhang"), ONE)
			.withOutput(new Text("jun"), ONE)
			.runTest();
	}
	
	@Test
	public void testReduce() {
		List<IntWritable> values = new ArrayList<IntWritable>();
		values.add(ONE);
		values.add(ONE);
		new ReduceDriver<Text,IntWritable,Text,IntWritable>()
			.withReducer(new JunzWordCount.IntSumReducer())
			.withInput(new Text("zhang"), values)
			.withOutput(new Text("zhang"), new IntWritable(2))
			.runTest();
	}

学习过程中可能需要修改源代码并测试执行,此时可以在Local Mode下运行Hadoop(Hadoop可以工作在三个模式,Local Mode,Pseudo-distributed, Distributed)。这里假定在JobClient.submitJobInternal()中增加一行LOG输出,这样在MapReduce Job提交的时候,就会输出该log:
  public 
  RunningJob submitJobInternal(final JobConf job
                               ) throws FileNotFoundException, 
                                        ClassNotFoundException,
                                        InterruptedException,
                                        IOException {
    /*
     * configure the command line options correctly on the submitting dfs
     */
    return ugi.doAs(new PrivilegedExceptionAction<RunningJob>() {
      public RunningJob run() throws FileNotFoundException, 
      ClassNotFoundException,
      InterruptedException,
      IOException{
    	//Add one log
    	LOG.info("Hello Junz");
Eclipse build完之后,将项目目录复制到VMware虚拟机的共享目录,在Guest CentOS下运行,可以看到输出的信息。通过查看./bin/hadoop启动脚本,可以知道它设定的classpath,$HADOOP_HOME/build/classes在$HADOOP_HOME/hadoop-core-1.0.4.jar之前,也就是说本地修改和编译的class优先被加载,因而可以看到修改后的代码反映在运行之中。


### Hadoop 自动打包工具类及其实现方式 在 Hadoop 开发中,自动打包是一个常见的需求,尤其是在频繁迭代和部署的情况下。下面详细介绍一种基于 Java 的工具类实现方法,该工具类可以简化 Hadoop 程序的打包过程。 #### 1. **创建自动打包工具类** 以下展示的是一个简单的 `JarUtil` 类,它可以用来自动化 Hadoop 程序的打包操作: ```java import java.io.File; import java.nio.file.Path; import java.nio.file.Paths; public class JarUtil { /** * 执行命令行指令的方法 * * @param command 命令字符串 */ private static void executeCommand(String command) { try { Process process = Runtime.getRuntime().exec(command); int exitCode = process.waitFor(); if (exitCode != 0) { throw new RuntimeException("Command execution failed with code: " + exitCode); } } catch (Exception e) { System.err.println("Failed to execute the command: " + command); e.printStackTrace(); } } /** * 自动生成 JAR 包的核心逻辑 * * @param sourceDir 源码根目录 * @param jarName 输出的 JAR 文件名 * @param mainClass 主类全限定名 */ public static void createJar(String sourceDir, String jarName, String mainClass) { Path currentRelativePath = Paths.get(""); String basePath = currentRelativePath.toAbsolutePath().toString(); // 清理旧文件 File oldJarFile = new File(basePath + "/" + jarName); if (oldJarFile.exists()) { oldJarFile.delete(); } // 构建 JAR 命令 StringBuilder jarCmdBuilder = new StringBuilder(); jarCmdBuilder.append("cd ").append(sourceDir).append("; ") .append("jar cf ").append(jarName).append(" -C ").append(sourceDir) .append("/target/classes .").append("; "); // 设置 Main-Class 属性 jarCmdBuilder.append("zipnote -w -e \"Main-Class: ").append(mainClass).append("\" ").append(jarName); // 执行命令 executeCommand(jarCmdBuilder.toString()); } } ``` 上述代码实现了通过命令行调用 `jar` 工具来自动生成 JAR 包的功能[^3]。它还支持指定主类(`Main-Class`),从而可以直接运行生成的 JAR 文件。 --- #### 2. **结合 Maven 或 Gradle 提高效率** 虽然手动编写工具类是一种可行的方式,但在现代开发实践中,通常建议使用成熟的构建工具如 Maven 或 Gradle 来完成类似的任务。以下是两种常见方案: ##### (1)Maven 方案 如果项目已经集成了 Maven,则可以通过配置 `maven-jar-plugin` 插件来实现自动打包功能。例如,在 `pom.xml` 中添加如下片段: ```xml <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-jar-plugin</artifactId> <version>3.2.0</version> <configuration> <archive> <manifest> <addClasspath>true</addClasspath> <mainClass>com.example.MainApp</mainClass> </manifest> </archive> </configuration> </plugin> </plugins> </build> ``` 这样每次执行 `mvn package` 命令时都会自动生成带有主类信息的可运行 JAR 文件[^5]。 ##### (2)Gradle 方案 对于使用 Gradle 的项目来说,也可以轻松实现相同的效果。只需在 `build.gradle` 文件中加入以下内容即可: ```gradle jar { manifest { attributes 'Main-Class': 'com.example.MainApp' } } ``` 之后运行 `gradle build` 即可在 `build/libs/` 路径下找到最终产物。 --- #### 3. **注意事项与问题解决** 当尝试在 IDE(如 IntelliJ IDEA)中进行自动打包时可能会遇到一些权限相关的问题。此时需确保已正确设置了环境变量 `HADOOP_USER_NAME`,否则可能导致类似以下错误提示: ``` Exception in thread "main" org.apache.hadoop.security.AccessControlException: Permission denied... ``` 可通过右键点击项目 -> Edit Configurations... -> VM options 字段输入 `-DHADOOP_USER_NAME=hdfs` 解决此类情况[^3]。 --- ### 总结 无论是借助于专门设计的小型工具类还是依托强大的构建管理系统,都可以有效提升 Hadoop 应用程序打包工作的便捷性和可靠性。选择合适的技术栈取决于团队习惯和个人偏好等因素综合考量结果而定。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值