docs: public static ExpressionFactory newInstance(Properties properties) {
          ExpressionFactory result = null;
          
          ClassLoader tccl;
          if (IS_SECURITY_ENABLED) {
              tccl = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
                  @Override
                  public ClassLoader run() {
                      return Thread.currentThread().getContextClassLoader();
                  }
              });
          } else {
              tccl = Thread.currentThread().getContextClassLoader();
          }
  
          //PM78648
          CacheValue cacheValue;
          Class<?> clazz;
  
          if (tccl == null) {
              cacheValue = nullTcclFactory;
          } else {
              CacheKey key = new CacheKey(tccl);
              cacheValue = factoryCache.get(key);
              if (cacheValue == null) {
                  CacheValue newCacheValue = new CacheValue();
                  cacheValue = factoryCache.putIfAbsent(key, newCacheValue);
                  if (cacheValue == null) {
                      cacheValue = newCacheValue;
                  }
              }
          }
  
          final Lock readLock = cacheValue.getLock().readLock();
          readLock.lock();
          try {
              clazz = cacheValue.getFactoryClass();
          } finally {
              readLock.unlock();
          }
  
          if (clazz == null) {
              String className = null;
              try {
                  final Lock writeLock = cacheValue.getLock().writeLock();
                  writeLock.lock();
                  try {
                      className = cacheValue.getFactoryClassName();
                      if (className == null) {
                          className = discoverClassName(tccl);
                          cacheValue.setFactoryClassName(className);
                      }
                      if (tccl == null) {
                          clazz = Class.forName(className);
                      } else {
                          clazz = tccl.loadClass(className);
                      }
                      cacheValue.setFactoryClass(clazz);
                  } finally {
                      writeLock.unlock();
                  }
              } catch (ClassNotFoundException e) {
                  throw new ELException(
                                  "Unable to find ExpressionFactory of type: " + className,
                                  e);
              }
          }
  
          try {
              Constructor<?> constructor = null;
              // Do we need to look for a constructor that will take properties?
              if (properties != null) {
                  try {
                      constructor = clazz.getConstructor(Properties.class);
                  } catch (SecurityException se) {
                      throw new ELException(se);
                  } catch (NoSuchMethodException nsme) {
                      // This can be ignored
                      // This is OK for this constructor not to exist
                  }
              }
              if (constructor == null) {
                  result = (ExpressionFactory) clazz.newInstance();
              } else {
                  result =
                      (ExpressionFactory) constructor.newInstance(properties);
              }
  
          } catch (InstantiationException e) {
              throw new ELException(
                      "Unable to create ExpressionFactory of type: " + clazz.getName(),
                      e);
          } catch (IllegalAccessException e) {
              throw new ELException(
                      "Unable to create ExpressionFactory of type: " + clazz.getName(),
                      e);
          } catch (IllegalArgumentException e) {
              throw new ELException(
                      "Unable to create ExpressionFactory of type: " + clazz.getName(),
                      e);
          } catch (InvocationTargetException e) {
              Throwable cause = e.getCause();
              if (cause instanceof ThreadDeath) {
                  throw (ThreadDeath) cause;
              }
              if (cause instanceof VirtualMachineError) {
                  throw (VirtualMachineError) cause;
              }
              throw new ELException(
                      "Unable to create ExpressionFactory of type: " + clazz.getName(),
                      e);
          }
          
          return result;
      }