public void registerUDFPlugin(HiveUDFPlugin instance) {
    Iterable<UDFDescriptor> x = instance.getDescriptors();
    for (UDFDescriptor fn : x) {
      if (UDF.class.isAssignableFrom(fn.getUDFClass())) {
        registerUDF(fn.getFunctionName(), (Class<? extends UDF>) fn.getUDFClass(), false);
        continue;
      }
      if (GenericUDAFResolver2.class.isAssignableFrom(fn.getUDFClass())) {
        String name = fn.getFunctionName();
        try {
          registerGenericUDAF(name, ((Class<? extends GenericUDAFResolver2>) fn.getUDFClass()).newInstance());
        } catch (InstantiationException | IllegalAccessException e) {
          throw new RuntimeException("Unable to register: " + name, e);
        }
        continue;
      }
      if (GenericUDTF.class.isAssignableFrom(fn.getUDFClass())) {
        registerGenericUDTF(fn.getFunctionName(), (Class<? extends GenericUDTF>) fn.getUDFClass());
        continue;
      }
      throw new RuntimeException("Don't know how to register: " + fn.getFunctionName());
    }
  }
This is called outside of the lock. Some of the methods that are called transitively by
this (e.g. addFunction) will take the lock again and then release it, which is ok.
ql/src/java/org/apache/hadoop/hive/ql/exec/Registry.java