在hive的源码中经常可以看到shims相关的类,shims相关类是用来兼容不同的hadoop和hive版本的,以HadoopShims为例org.apache.hadoop.hive.shims.HadoopShims是一个接口,具体的实现类为


org.apache.hadoop.hive.shims.Hadoop20Shims org.apache.hadoop.hive.shims.Hadoop20SShims org.apache.hadoop.hive.shims.Hadoop23Shims

具体对应的那个shims类在ShimLoader类(org.apache.hadoop.hive.shims.ShimLoader)中有所定义,以HADOOP_SHIM_CLASSES 为例:

 /**    * The names of the classes for shimming Hadoop for each major version.    */   private static final HashMap<String, String> HADOOP_SHIM_CLASSES =       new HashMap<String, String>();  // 首先定义了一个hashmap   static {     HADOOP_SHIM_CLASSES.put( "0.20", "org.apache.hadoop.hive.shims.Hadoop20Shims" );  // 0.20     HADOOP_SHIM_CLASSES.put( "0.20S", "org.apache.hadoop.hive.shims.Hadoop20SShims" );  // 1.x和0.20 security版本的hadoop     HADOOP_SHIM_CLASSES.put( "0.23", "org.apache.hadoop.hive.shims.Hadoop23Shims" ); // 2.x版本的hadoop   } // 向hashmap中插入对应的项,key为version信息,value为实际对应的类

ShimLoader类通过getHadoopShims方法返回具体的HadoopShims 

private static HadoopShims hadoopShims; ......   public static synchronized HadoopShims getHadoopShims() {     if (hadoopShims == null) {       hadoopShims = loadShims(HADOOP_SHIM_CLASSES, HadoopShims.class); // 调用loadShims方法     }     return hadoopShims;   }

而loadShims方法通过判断hadoop的版本,来获取hashmap中对应的设置类

  private static <T> T loadShims(Map<String, String> classMap, Class<T> xface) {     String vers = getMajorVersion();  // 获取hadoop的版本     String className = classMap.get(vers);     return createShim(className, xface);   }

具体哪个hadoop版本是由getMajorVersion获取,比如我们线上使用的是2.0.0-cdh4.6.0,那么getMajorVersion返回的值为0.23,对应的HadoopShims 实现类为org.apache.hadoop.hive.shims.Hadoop23Shims

 public static String getMajorVersion() {     String vers = VersionInfo.getVersion();  // org.apache.hadoop.util.VersionInfo类的getVersion方法   比如2.0.0-cdh4.6.0     String[] parts = vers.split( "\\.");     if (parts. length < 2) {       throw new RuntimeException("Illegal Hadoop Version: " + vers +           " (expected A.B.* format)");     }     // Special handling for Hadoop 1.x and 2.x     switch (Integer.parseInt(parts[0])) {     case 0:       break;     case 1:       return "0.20S";     case 2:       return "0.23";     default:       throw new IllegalArgumentException("Unrecognized Hadoop major version number: " + vers);     }     String majorVersion = parts[0] + "." + parts[1];     // If we are running a security release, we won't have UnixUserGroupInformation     // (removed by HADOOP-6299 when switching to JAAS for Login)     try {       Class.forName("org.apache.hadoop.security.UnixUserGroupInformation" );     } catch (ClassNotFoundException cnf) {       if ("0.20".equals(majorVersion)) {         majorVersion += "S";       }     }     return majorVersion;   }

而不同的shims中规定了不同版本下的属性和方法等,比如判断是否localmode:

1). Hadoop20SShims 类(Hadoop 0.20 with Security和1.x版本 )

  @Override   public boolean isLocalMode(Configuration conf) {     return "local".equals(getJobLauncherRpcAddress(conf));   }   @Override   public String getJobLauncherRpcAddress( Configuration conf) { //通过判断mapred.job.tracker的设置     return conf.get( "mapred.job.tracker");   }


2).Hadoop20Shims类 (Hadoop 0.20版本) 同上
3).Hadoop23Shims  (Hadoop 2.x版本)

  @Override   public boolean isLocalMode( Configuration conf) {     return "local".equals(conf.get("mapreduce.framework.name" ));   //根据mapreduce.framework.name设置   }