You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@uima.apache.org by re...@apache.org on 2021/12/09 18:23:56 UTC

[uima-uimaj] branch maintenance/3.2.x updated: [UIMA-6398] Classloader paradoxon and memory leak in UIMA loggers

This is an automated email from the ASF dual-hosted git repository.

rec pushed a commit to branch maintenance/3.2.x
in repository https://gitbox.apache.org/repos/asf/uima-uimaj.git


The following commit(s) were added to refs/heads/maintenance/3.2.x by this push:
     new e050dfa  [UIMA-6398] Classloader paradoxon and memory leak in UIMA loggers
e050dfa is described below

commit e050dfafa1e7102459de7f44b9720477deaaee88
Author: Richard Eckart de Castilho <re...@apache.org>
AuthorDate: Thu Dec 9 19:18:57 2021 +0100

    [UIMA-6398] Classloader paradoxon and memory leak in UIMA loggers
    
    - Log regressive warning if resource manager is set in a logger
    - Look for resource manager in UimaContextHolder or try context classloader in thread to look up message bundles
    - Remove setting the logger resource manager in initalize methods of FlowControllers, Engines and Resources
---
 .../asb/impl/FlowControllerContainer.java          |   6 +-
 .../impl/PrimitiveAnalysisEngine_impl.java         |  31 +++---
 .../apache/uima/resource/Resource_ImplBase.java    |  11 +--
 .../src/main/java/org/apache/uima/util/Logger.java | 108 +++++++++++----------
 .../apache/uima/util/impl/Logger_common_impl.java  |  74 ++++++++++----
 .../impl/AnalysisEngineDescription_implTest.java   |   1 -
 6 files changed, 140 insertions(+), 91 deletions(-)

diff --git a/uimaj-core/src/main/java/org/apache/uima/analysis_engine/asb/impl/FlowControllerContainer.java b/uimaj-core/src/main/java/org/apache/uima/analysis_engine/asb/impl/FlowControllerContainer.java
index 21971a2..55bdda5 100644
--- a/uimaj-core/src/main/java/org/apache/uima/analysis_engine/asb/impl/FlowControllerContainer.java
+++ b/uimaj-core/src/main/java/org/apache/uima/analysis_engine/asb/impl/FlowControllerContainer.java
@@ -41,7 +41,6 @@ import org.apache.uima.flow.FlowControllerContext;
 import org.apache.uima.flow.FlowControllerDescription;
 import org.apache.uima.flow.JCasFlow_ImplBase;
 import org.apache.uima.impl.Util;
-import org.apache.uima.internal.util.Class_TCCL;
 import org.apache.uima.internal.util.JmxMBeanAgent;
 import org.apache.uima.resource.ConfigurableResource_ImplBase;
 import org.apache.uima.resource.ResourceConfigurationException;
@@ -78,6 +77,7 @@ public class FlowControllerContainer extends ConfigurableResource_ImplBase {
    *      
    * UIMA-5043 Set & restore the UimaContextHolder around calls to user code so it can be used to access the External Settings
    */
+  @Override
   public boolean initialize(ResourceSpecifier aSpecifier, Map<String, Object> aAdditionalParams)
           throws ResourceInitializationException {
     UimaContext prevContext = setContextHolder();   // Get this early so the restore in correct
@@ -122,7 +122,6 @@ public class FlowControllerContainer extends ConfigurableResource_ImplBase {
       // Set Logger, to enable component-specific logging configuration
       UimaContextAdmin uimaContext = getUimaContextAdmin();
       Logger logger = UIMAFramework.getLogger(mFlowController.getClass());
-      logger.setResourceManager(this.getResourceManager());
       uimaContext.setLogger(logger);
       
       Logger classLogger = getLogger();
@@ -162,6 +161,7 @@ public class FlowControllerContainer extends ConfigurableResource_ImplBase {
    * 
    * @see java.lang.Object#finalize()
    */
+  @Override
   protected void finalize() throws Throwable {
     // unregister MBean from MBeanServer when GC occurs
     // NOTE: we don't want to do this in destroy() because all AEs in a CPE are
@@ -181,6 +181,7 @@ public class FlowControllerContainer extends ConfigurableResource_ImplBase {
    * 
    * @see org.apache.uima.resource.ConfigurableResource_ImplBase#reconfigure()
    */
+  @Override
   public void reconfigure() throws ResourceConfigurationException {
     UimaContext prevContext = setContextHolder();  // for use by POJOs
     try {
@@ -197,6 +198,7 @@ public class FlowControllerContainer extends ConfigurableResource_ImplBase {
    * 
    * @see org.apache.uima.resource.Resource_ImplBase#destroy()
    */
+  @Override
   public void destroy() {
     withContextHolder(() -> mFlowController.destroy());
     super.destroy();
diff --git a/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/PrimitiveAnalysisEngine_impl.java b/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/PrimitiveAnalysisEngine_impl.java
index 0913b93..212f7ff 100644
--- a/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/PrimitiveAnalysisEngine_impl.java
+++ b/uimaj-core/src/main/java/org/apache/uima/analysis_engine/impl/PrimitiveAnalysisEngine_impl.java
@@ -26,7 +26,6 @@ import org.apache.uima.Constants;
 import org.apache.uima.UIMAFramework;
 import org.apache.uima.UIMA_IllegalStateException;
 import org.apache.uima.UimaContext;
-import org.apache.uima.UimaContextAdmin;
 import org.apache.uima.UimaContextHolder;
 import org.apache.uima.analysis_component.AnalysisComponent;
 import org.apache.uima.analysis_engine.AnalysisEngine;
@@ -52,7 +51,6 @@ import org.apache.uima.resource.metadata.ProcessingResourceMetaData;
 import org.apache.uima.resource.metadata.ResourceMetaData;
 import org.apache.uima.util.Level;
 import org.apache.uima.util.Logger;
-import org.slf4j.MDC;
 
 /**
  * Reference implementation of {@link AnalysisEngine}.
@@ -106,6 +104,7 @@ public class PrimitiveAnalysisEngine_impl extends AnalysisEngineImplBase impleme
   /**
    * @see org.apache.uima.resource.Resource#initialize(ResourceSpecifier, Map)
    */
+  @Override
   public boolean initialize(ResourceSpecifier aSpecifier, Map<String, Object> aAdditionalParams)
           throws ResourceInitializationException {
     try {
@@ -240,15 +239,12 @@ public class PrimitiveAnalysisEngine_impl extends AnalysisEngineImplBase impleme
                   annotatorClassName, mDescription.getSourceUrlString() }, e);
     }
 
-    // Set Logger, to enable annotator-specific logging
-    UimaContextAdmin uimaContext = getUimaContextAdmin();
-    Logger logger = UIMAFramework.getLogger(annotatorClass);
-    logger.setResourceManager(this.getResourceManager());
-    uimaContext.setLogger(logger);
-
     // initialize AnalysisComponent
     UimaContext prevContext = setContextHolder();  // for use by POJOs
     try {
+      // Set Logger, to enable annotator-specific logging
+      getUimaContextAdmin().setLogger(UIMAFramework.getLogger(annotatorClass));
+
       callInitializeMethod(mAnalysisComponent, getUimaContext());
 //      mAnalysisComponent.initialize(getUimaContext());
       // set up the CAS pool for this AE (this won't do anything if mAnalysisComponent.getCasInstancesRequired() == 0)
@@ -266,6 +262,7 @@ public class PrimitiveAnalysisEngine_impl extends AnalysisEngineImplBase impleme
   /**
    * @see org.apache.uima.resource.Resource#destroy()
    */
+  @Override
   public void destroy() {
     if (mAnalysisComponent != null) {
       withContextHolder(() -> mAnalysisComponent.destroy());
@@ -280,6 +277,7 @@ public class PrimitiveAnalysisEngine_impl extends AnalysisEngineImplBase impleme
    * 
    * @see org.apache.uima.analysis_engine.AnalysisEngine#setResultSpecification(org.apache.uima.analysis_engine.ResultSpecification)
    */
+  @Override
   public void setResultSpecification(ResultSpecification aResultSpec) {
     if (aResultSpec == null) {
       resetResultSpecificationToDefault();
@@ -292,6 +290,7 @@ public class PrimitiveAnalysisEngine_impl extends AnalysisEngineImplBase impleme
   /**
    * @see AnalysisEngine#processAndOutputNewCASes(CAS)
    */
+  @Override
   public CasIterator processAndOutputNewCASes(CAS aCAS) throws AnalysisEngineProcessException {
     enterProcess();
     try {
@@ -306,6 +305,7 @@ public class PrimitiveAnalysisEngine_impl extends AnalysisEngineImplBase impleme
     }
   }
 
+  @Override
   public void batchProcessComplete() throws AnalysisEngineProcessException {
     enterBatchProcessComplete();
     UimaContext prevContext = setContextHolder();  // for use by POJOs
@@ -317,6 +317,7 @@ public class PrimitiveAnalysisEngine_impl extends AnalysisEngineImplBase impleme
     }
   }
 
+  @Override
   public void collectionProcessComplete() throws AnalysisEngineProcessException {
     enterCollectionProcessComplete();
     UimaContext prevContext = setContextHolder();  // for use by POJOs
@@ -422,10 +423,11 @@ public class PrimitiveAnalysisEngine_impl extends AnalysisEngineImplBase impleme
     } catch (Exception e) {
       // log and rethrow exception
       logger.log(Level.SEVERE, "", e);
-      if (e instanceof AnalysisEngineProcessException)
+      if (e instanceof AnalysisEngineProcessException) {
         throw (AnalysisEngineProcessException) e;
-      else
+      } else {
         throw new AnalysisEngineProcessException(e);
+      }
     }
   }
 
@@ -541,10 +543,11 @@ public class PrimitiveAnalysisEngine_impl extends AnalysisEngineImplBase impleme
     } catch (Exception e) {
       // log and rethrow exception
       getLogger().log(Level.SEVERE, "", e);
-      if (e instanceof AnalysisEngineProcessException)
+      if (e instanceof AnalysisEngineProcessException) {
         throw (AnalysisEngineProcessException) e;
-      else
+      } else {
         throw new AnalysisEngineProcessException(e);
+      }
     } finally {
       UimaContextHolder.setContext(prevContext);
     }
@@ -553,6 +556,7 @@ public class PrimitiveAnalysisEngine_impl extends AnalysisEngineImplBase impleme
   /**
    * @see org.apache.uima.analysis_engine.AnalysisEngine#reconfigure()
    */
+  @Override
   public void reconfigure() throws ResourceConfigurationException {
     // do base resource reconfiguration
     super.reconfigure();
@@ -591,6 +595,7 @@ public class PrimitiveAnalysisEngine_impl extends AnalysisEngineImplBase impleme
      * 
      * @see org.apache.uima.core.CasIterator#hasNext()
      */
+    @Override
     public boolean hasNext() throws AnalysisEngineProcessException {
       enterProcess();
       if (casAvailable) {
@@ -626,6 +631,7 @@ public class PrimitiveAnalysisEngine_impl extends AnalysisEngineImplBase impleme
      * 
      * @see org.apache.uima.core.CasIterator#next(java.lang.Class)
      */
+    @Override
     public CAS next() throws AnalysisEngineProcessException {
       enterProcess();
       try {
@@ -659,6 +665,7 @@ public class PrimitiveAnalysisEngine_impl extends AnalysisEngineImplBase impleme
      * 
      * @see org.apache.uima.analysis_engine.CasIterator#release()
      */
+    @Override
     public void release() {
       // nothing to do
     }
diff --git a/uimaj-core/src/main/java/org/apache/uima/resource/Resource_ImplBase.java b/uimaj-core/src/main/java/org/apache/uima/resource/Resource_ImplBase.java
index 9b7e9bc..3d1b65d 100644
--- a/uimaj-core/src/main/java/org/apache/uima/resource/Resource_ImplBase.java
+++ b/uimaj-core/src/main/java/org/apache/uima/resource/Resource_ImplBase.java
@@ -89,8 +89,8 @@ public abstract class Resource_ImplBase implements Resource {
     if (aAdditionalParams != null) {
       mUimaContextAdmin = (UimaContextAdmin) aAdditionalParams.get(PARAM_UIMA_CONTEXT);
     }
+
     if (mUimaContextAdmin == null) {// no, we have to create one    
-    
       // skip this part if initializing an external resource
       // https://issues.apache.org/jira/browse/UIMA-5153
       if (!(aSpecifier instanceof ConfigurableDataResourceSpecifier) &&
@@ -108,8 +108,7 @@ public abstract class Resource_ImplBase implements Resource {
         // get a Logger for this class and set its ResourceManager so that
         // UIMA extension ClassLoader is used to locate message digests.
         Logger logger = UIMAFramework.getLogger(this.getClass());
-        logger.setResourceManager(resMgr);
-      
+
         ConfigurationManager configMgr = null;
         if (aAdditionalParams != null) {
           configMgr = (ConfigurationManager)aAdditionalParams.get(PARAM_CONFIG_MANAGER);
@@ -133,7 +132,6 @@ public abstract class Resource_ImplBase implements Resource {
       // get a Logger for this class and set its ResourceManager so that
       // UIMA extension ClassLoader is used to locate message digests.
       Logger logger = UIMAFramework.getLogger(this.getClass());
-      logger.setResourceManager(mUimaContextAdmin.getResourceManager());
       mUimaContextAdmin.setLogger(logger);
     }
 
@@ -289,10 +287,11 @@ public abstract class Resource_ImplBase implements Resource {
    */
   @Override
   public ResourceManager getResourceManager() {
-    if (getUimaContextAdmin() != null)
+    if (getUimaContextAdmin() != null) {
       return getUimaContextAdmin().getResourceManager();
-    else
+    } else {
       return null;
+    }
   }
 
   /*
diff --git a/uimaj-core/src/main/java/org/apache/uima/util/Logger.java b/uimaj-core/src/main/java/org/apache/uima/util/Logger.java
index 8b9eb42..174d62e 100644
--- a/uimaj-core/src/main/java/org/apache/uima/util/Logger.java
+++ b/uimaj-core/src/main/java/org/apache/uima/util/Logger.java
@@ -24,7 +24,7 @@ import java.io.PrintStream;
 import java.util.function.Supplier;
 
 import org.apache.uima.UIMAException;
-import org.apache.uima.UIMARuntimeException;
+import org.apache.uima.UimaContextHolder;
 import org.apache.uima.resource.ResourceManager;
 import org.slf4j.Marker;
 import org.slf4j.MarkerFactory;
@@ -55,8 +55,8 @@ import org.slf4j.MarkerFactory;
 public interface Logger extends org.slf4j.Logger {
 
   // standard markers
-  static final Marker UIMA_MARKER_CONFIG = MarkerFactory.getMarker("org.apache.uima.config");
-  static final Marker UIMA_MARKER_FINEST = MarkerFactory.getMarker("org.apache.uima.finest");
+  Marker UIMA_MARKER_CONFIG = MarkerFactory.getMarker("org.apache.uima.config");
+  Marker UIMA_MARKER_FINEST = MarkerFactory.getMarker("org.apache.uima.finest");
 
   /**
    * Logs a message.
@@ -66,8 +66,7 @@ public interface Logger extends org.slf4j.Logger {
    * @param aMessage
    *          the message to be logged with message level INFO
    */
-  @Deprecated
-  public void log(String aMessage);
+  @Deprecated void log(String aMessage);
 
   /**
    * Logs an internationalized message.
@@ -81,8 +80,7 @@ public interface Logger extends org.slf4j.Logger {
    * @param aArguments
    *          arguments to message (may be null if none)
    */
-  @Deprecated
-public void log(String aResourceBundleName, String aMessageKey, Object[] aArguments);
+  @Deprecated void log(String aResourceBundleName, String aMessageKey, Object[] aArguments);
 
   /**
    * Logs an exception
@@ -92,8 +90,7 @@ public void log(String aResourceBundleName, String aMessageKey, Object[] aArgume
    * @param aException
    *          the exception to be logged with message level INFO
    */
-  @Deprecated
-public void logException(Exception aException);
+  @Deprecated void logException(Exception aException);
 
   /**
    * Sets the output stream to which log messages will go. Setting the output stream to
@@ -104,8 +101,7 @@ public void logException(Exception aException);
    * @param aStream
    *          <code>PrintStream</code> to which log messages will be printed
    */
-  @Deprecated
-public void setOutputStream(PrintStream aStream);
+  @Deprecated void setOutputStream(PrintStream aStream);
 
   /**
    * Sets the output stream to which log messages will go. Setting the output stream to
@@ -116,8 +112,7 @@ public void setOutputStream(PrintStream aStream);
    * @param aStream
    *          <code>OutputStream</code> to which log messages will be printed
    */
-  @Deprecated
-public void setOutputStream(OutputStream aStream);
+  @Deprecated void setOutputStream(OutputStream aStream);
 
   /**
    * Logs a message.
@@ -127,7 +122,7 @@ public void setOutputStream(OutputStream aStream);
    * @param aMessage
    *          the message to be logged
    */
-  public void log(Level level, String aMessage);
+  void log(Level level, String aMessage);
 
   /**
    * Logs a message with one parameter
@@ -139,7 +134,7 @@ public void setOutputStream(OutputStream aStream);
    * @param param1
    *          message parameter
    */
-  public void log(Level level, String aMessage, Object param1);
+  void log(Level level, String aMessage, Object param1);
 
   /**
    * Logs a message with an arbitrary number of parameters
@@ -151,7 +146,7 @@ public void setOutputStream(OutputStream aStream);
    * @param params
    *          message parameter array
    */
-  public void log(Level level, String aMessage, Object[] params);
+  void log(Level level, String aMessage, Object[] params);
 
   /**
    * Logs a message and a throwable object
@@ -163,7 +158,7 @@ public void setOutputStream(OutputStream aStream);
    * @param thrown
    *          throwable object
    */
-  public void log(Level level, String aMessage, Throwable thrown);
+  void log(Level level, String aMessage, Throwable thrown);
 
   /**
    * Logs a message with a message key. The real message is extracted from a resource bundle.
@@ -179,7 +174,7 @@ public void setOutputStream(OutputStream aStream);
    * @param msgKey
    *          message key
    */
-  public void logrb(Level level, String sourceClass, String sourceMethod, String bundleName,
+  void logrb(Level level, String sourceClass, String sourceMethod, String bundleName,
           String msgKey);
 
   /**
@@ -199,7 +194,7 @@ public void setOutputStream(OutputStream aStream);
    * @param param1
    *          message parameter
    */
-  public void logrb(Level level, String sourceClass, String sourceMethod, String bundleName,
+  void logrb(Level level, String sourceClass, String sourceMethod, String bundleName,
           String msgKey, Object param1);
 
   /**
@@ -219,7 +214,7 @@ public void setOutputStream(OutputStream aStream);
    * @param params
    *          message parameter array with an arbitrary number of parameters
    */
-  public void logrb(Level level, String sourceClass, String sourceMethod, String bundleName,
+  void logrb(Level level, String sourceClass, String sourceMethod, String bundleName,
           String msgKey, Object[] params);
 
   /**
@@ -239,7 +234,7 @@ public void setOutputStream(OutputStream aStream);
    * @param thrown
    *          throwable object
    */
-  public void logrb(Level level, String sourceClass, String sourceMethod, String bundleName,
+  void logrb(Level level, String sourceClass, String sourceMethod, String bundleName,
           String msgKey, Throwable thrown);
 
   /**
@@ -254,7 +249,7 @@ public void setOutputStream(OutputStream aStream);
    * @param thrown
    *          throwable object
    */
-  public void log(String wrapperFQCN, Level level, String message, Throwable thrown);
+  void log(String wrapperFQCN, Level level, String message, Throwable thrown);
   
   /**
    * Checks if the argument level is greater or equal to the specified level
@@ -264,7 +259,7 @@ public void setOutputStream(OutputStream aStream);
    * 
    * @return boolean - true if the argument level is greater or equal to the specified level
    */
-  public boolean isLoggable(Level level);
+  boolean isLoggable(Level level);
   
   /**
    * Checks if this logger is enabled for this level and this marker
@@ -272,7 +267,7 @@ public void setOutputStream(OutputStream aStream);
    * @param marker null or the marker to test
    * @return true if the level is greater or equal to the specified level and the marker matches
    */
-  public boolean isLoggable(Level level, Marker marker);
+  boolean isLoggable(Level level, Marker marker);
 
   /**
    * Sets the level of messages that will be logged by this logger. Note that if you call
@@ -287,7 +282,7 @@ public void setOutputStream(OutputStream aStream);
    * @param level
    *          message level
    */
-  public void setLevel(Level level);
+  void setLevel(Level level);
 
   /**
    * Sets the ResourceManager to use for message localization. This method is intended for use by
@@ -296,8 +291,17 @@ public void setOutputStream(OutputStream aStream);
    * @param resourceManager
    *          A resource manager instance whose extension ClassLoader (if any) will be used for
    *          message localization by this logger.
+   * @deprecated When a logger is used within UIMA, the resource manager is picked up from the
+   *             {@link UimaContextHolder} and if none is available, then the class loader set on
+   *             the {@link Thread#getContextClassLoader()} is used. Thus, setting a resource
+   *             manager for loading message localizations should not be required. Setting a
+   *             resource manager anyway can lead to resource being registered in the resource
+   *             manager to not be garbage collected in a timely manner. Also, the logger is shared
+   *             globally and in a multi-threaded/multi-classloader scenario, it is likely that
+   *             different threads overwrite each others logger resource manager making it likely
+   *             that in any given thread the wrong resource manager is used by the logger.
    */
-  public void setResourceManager(ResourceManager resourceManager);
+  @Deprecated void setResourceManager(ResourceManager resourceManager);
 
   /**
    * Get an internationalized message from a resource bundle by key name, substituting the parameters.
@@ -307,7 +311,7 @@ public void setOutputStream(OutputStream aStream);
    * @param params -
    * @return the internationalized message
    */
-  public String rb(String resourceBundle, String key, Object... params);
+  String rb(String resourceBundle, String key, Object... params);
   
   default String rb_ue(String key, Object... params) {
     return rb(UIMAException.STANDARD_MESSAGE_CATALOG, key, params);
@@ -319,7 +323,7 @@ public void setOutputStream(OutputStream aStream);
    * and CPP components.
    * @return true if this logger is an Annotator logger.
    */
-  public boolean isAnnotatorLogger();
+  boolean isAnnotatorLogger();
 
   /**
    * @param limit the limit
@@ -340,33 +344,33 @@ public void setOutputStream(OutputStream aStream);
    * @param msgSupplier A function, which when called, produces the desired log message
    * @param throwable the exception to log
    */
-  public void debug(Supplier<String> msgSupplier, Throwable throwable);
+  void debug(Supplier<String> msgSupplier, Throwable throwable);
   
   /**
    * @param marker the marker data specific to this log statement
    * @param message the message to log
    * @param paramSuppliers An array of functions, which when called, produce the desired log message parameters.
    */
-  public void debug(Marker marker, String message, Supplier<?>... paramSuppliers);
+  void debug(Marker marker, String message, Supplier<?>... paramSuppliers);
 
   /**
    * @param message the message to log
    * @param paramSuppliers An array of functions, which when called, produce the desired log message parameters.
    */
-  public void debug(String message, Supplier<?>... paramSuppliers);
+  void debug(String message, Supplier<?>... paramSuppliers);
 
   /**
    * @param marker the marker data specific to this log statement
    * @param msgSupplier A function, which when called, produces the desired log message
    */
-  public void debug(Marker marker, Supplier<String> msgSupplier);
+  void debug(Marker marker, Supplier<String> msgSupplier);
 
   /**
    * @param marker the marker data specific to this log statement
    * @param msgSupplier A function, which when called, produces the desired log message
    * @param throwable the exception to log
    */
-  public void debug(Marker marker, Supplier<String> msgSupplier, Throwable throwable);
+  void debug(Marker marker, Supplier<String> msgSupplier, Throwable throwable);
 
   /**
    * @param msgSupplier A function, which when called, produces the desired log message
@@ -377,33 +381,33 @@ public void setOutputStream(OutputStream aStream);
    * @param msgSupplier A function, which when called, produces the desired log message
    * @param throwable the exception to log
    */
-  public void error(Supplier<String> msgSupplier, Throwable throwable);
+  void error(Supplier<String> msgSupplier, Throwable throwable);
   
   /**
    * @param marker the marker data specific to this log statement
    * @param message the message to log
    * @param paramSuppliers An array of functions, which when called, produce the desired log message parameters.
    */
-  public void error(Marker marker, String message, Supplier<?>... paramSuppliers);
+  void error(Marker marker, String message, Supplier<?>... paramSuppliers);
 
   /**
    * @param message the message to log
    * @param paramSuppliers An array of functions, which when called, produce the desired log message parameters.
    */
-  public void error(String message, Supplier<?>... paramSuppliers);
+  void error(String message, Supplier<?>... paramSuppliers);
 
   /**
    * @param marker the marker data specific to this log statement
    * @param msgSupplier A function, which when called, produces the desired log message
    */
-  public void error(Marker marker, Supplier<String> msgSupplier);
+  void error(Marker marker, Supplier<String> msgSupplier);
 
   /**
    * @param marker the marker data specific to this log statement
    * @param msgSupplier A function, which when called, produces the desired log message
    * @param throwable the exception to log
    */
-  public void error(Marker marker, Supplier<String> msgSupplier, Throwable throwable);
+  void error(Marker marker, Supplier<String> msgSupplier, Throwable throwable);
 
   /**
    * @param msgSupplier A function, which when called, produces the desired log message
@@ -414,27 +418,27 @@ public void setOutputStream(OutputStream aStream);
    * @param msgSupplier A function, which when called, produces the desired log message
    * @param throwable the exception to log
    */
-  public void info(Supplier<String> msgSupplier, Throwable throwable);
+  void info(Supplier<String> msgSupplier, Throwable throwable);
   
   /**
    * @param marker the marker data specific to this log statement
    * @param message the message to log
    * @param paramSuppliers An array of functions, which when called, produce the desired log message parameters.
    */
-  public void info(Marker marker, String message, Supplier<?>... paramSuppliers);
+  void info(Marker marker, String message, Supplier<?>... paramSuppliers);
 
   /**
    * @param marker the marker data specific to this log statement
    * @param msgSupplier A function, which when called, produces the desired log message
    */
-  public void info(Marker marker, Supplier<String> msgSupplier);
+  void info(Marker marker, Supplier<String> msgSupplier);
 
   /**
    * @param marker the marker data specific to this log statement
    * @param msgSupplier A function, which when called, produces the desired log message
    * @param throwable the exception to log
    */
-  public void info(Marker marker, Supplier<String> msgSupplier, Throwable throwable);
+  void info(Marker marker, Supplier<String> msgSupplier, Throwable throwable);
 
   /**
    * @param msgSupplier A function, which when called, produces the desired log message
@@ -445,33 +449,33 @@ public void setOutputStream(OutputStream aStream);
    * @param msgSupplier A function, which when called, produces the desired log message
    * @param throwable the exception to log
    */
-  public void trace(Supplier<String> msgSupplier, Throwable throwable);
+  void trace(Supplier<String> msgSupplier, Throwable throwable);
   
   /**
    * @param marker the marker data specific to this log statement
    * @param message the message to log
    * @param paramSuppliers An array of functions, which when called, produce the desired log message parameters.
    */
-  public void trace(Marker marker, String message, Supplier<?>... paramSuppliers);
+  void trace(Marker marker, String message, Supplier<?>... paramSuppliers);
 
   /**
    * @param message the message to log
    * @param paramSuppliers An array of functions, which when called, produce the desired log message parameters.
    */
-  public void trace(String message, Supplier<?>... paramSuppliers);
+  void trace(String message, Supplier<?>... paramSuppliers);
 
   /**
    * @param marker the marker data specific to this log statement
    * @param msgSupplier A function, which when called, produces the desired log message
    */
-  public void trace(Marker marker, Supplier<String> msgSupplier);
+  void trace(Marker marker, Supplier<String> msgSupplier);
 
   /**
    * @param marker the marker data specific to this log statement
    * @param msgSupplier A function, which when called, produces the desired log message
    * @param throwable the exception to log
    */
-  public void trace(Marker marker, Supplier<String> msgSupplier, Throwable throwable);
+  void trace(Marker marker, Supplier<String> msgSupplier, Throwable throwable);
 
   /**
    * @param msgSupplier A function, which when called, produces the desired log message
@@ -482,32 +486,32 @@ public void setOutputStream(OutputStream aStream);
    * @param msgSupplier A function, which when called, produces the desired log message
    * @param throwable the exception to log
    */
-  public void warn(Supplier<String> msgSupplier, Throwable throwable);
+  void warn(Supplier<String> msgSupplier, Throwable throwable);
   
   /**
    * @param marker the marker data specific to this log statement
    * @param message the message to log
    * @param paramSuppliers An array of functions, which when called, produce the desired log message parameters.
    */
-  public void warn(Marker marker, String message, Supplier<?>... paramSuppliers);
+  void warn(Marker marker, String message, Supplier<?>... paramSuppliers);
 
   /**
    * @param message the message to log
    * @param paramSuppliers An array of functions, which when called, produce the desired log message parameters.
    */
-  public void warn(String message, Supplier<?>... paramSuppliers);
+  void warn(String message, Supplier<?>... paramSuppliers);
 
   /**
    * @param marker the marker data specific to this log statement
    * @param msgSupplier A function, which when called, produces the desired log message
    */
-  public void warn(Marker marker, Supplier<String> msgSupplier);
+  void warn(Marker marker, Supplier<String> msgSupplier);
 
   /**
    * @param marker the marker data specific to this log statement
    * @param msgSupplier A function, which when called, produces the desired log message
    * @param throwable the exception to log
    */
-  public void warn(Marker marker, Supplier<String> msgSupplier, Throwable throwable);
+  void warn(Marker marker, Supplier<String> msgSupplier, Throwable throwable);
 
 }
diff --git a/uimaj-core/src/main/java/org/apache/uima/util/impl/Logger_common_impl.java b/uimaj-core/src/main/java/org/apache/uima/util/impl/Logger_common_impl.java
index 8d4d686..6a71496 100644
--- a/uimaj-core/src/main/java/org/apache/uima/util/impl/Logger_common_impl.java
+++ b/uimaj-core/src/main/java/org/apache/uima/util/impl/Logger_common_impl.java
@@ -22,8 +22,13 @@ package org.apache.uima.util.impl;
 import java.io.OutputStream;
 import java.io.PrintStream;
 import java.text.MessageFormat;
+import java.util.concurrent.atomic.AtomicInteger;
 import java.util.function.Supplier;
 
+import org.apache.uima.UIMAFramework;
+import org.apache.uima.UimaContext;
+import org.apache.uima.UimaContextAdmin;
+import org.apache.uima.UimaContextHolder;
 import org.apache.uima.internal.util.I18nUtil;
 import org.apache.uima.internal.util.Misc;
 import org.apache.uima.resource.ResourceManager;
@@ -90,10 +95,21 @@ public abstract class Logger_common_impl implements Logger {
   
   protected final int limit_common;
   private final boolean isLimited; // master switch tested first
+  private final AtomicInteger dontSetResourceManagerCount = new AtomicInteger();
 
   /**
    * ResourceManager whose extension ClassLoader will be used to locate the message digests. Null
    * will cause the ClassLoader to default to this.class.getClassLoader().
+   * 
+   * @Deprecated When a logger is used within UIMA, the resource manager is picked up from the
+   *             {@link UimaContextHolder} and if none is available, then the class loader set on
+   *             the {@link Thread#getContextClassLoader()} is used. Thus, setting a resource
+   *             manager for loading message localizations should not be required. Setting a
+   *             resource manager anyway can lead to resource being registered in the resource
+   *             manager to not be garbage collected in a timely manner. Also, the logger is shared
+   *             globally and in a multi-threaded/multi-classloader scenario, it is likely that
+   *             different threads overwrite each others logger resource manager making it likely
+   *             that in any given thread the wrong resource manager is used by the logger.
    */
   private ResourceManager mResourceManager = null;
   private boolean isAnnotatorLogger;
@@ -116,9 +132,7 @@ public abstract class Logger_common_impl implements Logger {
   }   
   
   /*********************************************
-   * Abstract methods 
-   * not in Uima Logger interface
-   * that must be implemented by subclasses
+   * Abstract methods not in UIMA Logger interface that must be implemented by subclasses
    *********************************************/
 
   /**
@@ -206,13 +220,27 @@ public abstract class Logger_common_impl implements Logger {
       return true;
     }
     switch(level.toInteger()) {
-    case Level.SEVERE_INT: if (SEVERE_COUNT >= limit_common) return false; SEVERE_COUNT++; return true; 
-    case Level.WARNING_INT: if (WARNING_COUNT >= limit_common) return false; WARNING_COUNT++; return true; 
-    case Level.INFO_INT: if (INFO_COUNT >= limit_common) return false; INFO_COUNT++; return true; 
-    case Level.CONFIG_INT: if (CONFIG_COUNT >= limit_common) return false; CONFIG_COUNT++; return true; 
-    case Level.FINE_INT: if (FINE_COUNT >= limit_common) return false; FINE_COUNT++; return true; 
-    case Level.FINER_INT: if (FINER_COUNT >= limit_common) return false; FINER_COUNT++; return true; 
-    case Level.FINEST_INT: if (FINEST_COUNT >= limit_common) return false; FINEST_COUNT++; return true; 
+    case Level.SEVERE_INT: if (SEVERE_COUNT >= limit_common) {
+      return false;
+    } SEVERE_COUNT++; return true; 
+    case Level.WARNING_INT: if (WARNING_COUNT >= limit_common) {
+      return false;
+    } WARNING_COUNT++; return true; 
+    case Level.INFO_INT: if (INFO_COUNT >= limit_common) {
+      return false;
+    } INFO_COUNT++; return true; 
+    case Level.CONFIG_INT: if (CONFIG_COUNT >= limit_common) {
+      return false;
+    } CONFIG_COUNT++; return true; 
+    case Level.FINE_INT: if (FINE_COUNT >= limit_common) {
+      return false;
+    } FINE_COUNT++; return true; 
+    case Level.FINER_INT: if (FINER_COUNT >= limit_common) {
+      return false;
+    } FINER_COUNT++; return true; 
+    case Level.FINEST_INT: if (FINEST_COUNT >= limit_common) {
+      return false;
+    } FINEST_COUNT++; return true; 
     }
     Misc.internalError();
     return false;
@@ -407,14 +435,13 @@ public abstract class Logger_common_impl implements Logger {
     }
   }
 
-  /*
-   * (non-Javadoc)
-   * 
-   * @see org.apache.uima.util.Logger#setResourceManager(org.apache.uima.resource.ResourceManager)
-   */
+  @Deprecated
   @Override
   public void setResourceManager(ResourceManager resourceManager) {
     mResourceManager = resourceManager;
+    Misc.decreasingWithTrace(dontSetResourceManagerCount,
+            "Setting a resouce manager on a logger can lead to memory leaks and to the inability of locating message localizations in multi-classloader scenaros.",
+            UIMAFramework.getLogger());
   }
 
   /**
@@ -422,11 +449,22 @@ public abstract class Logger_common_impl implements Logger {
    * then message digests will be searched for using this.class.getClassLoader().
    */
   private ClassLoader getExtensionClassLoader() {
-    if (mResourceManager == null)
-      return null;
-    else
+    if (mResourceManager != null) {
       return mResourceManager.getExtensionClassLoader();
     }
+
+    UimaContext context = UimaContextHolder.getContext();
+    if (context != null) {
+      return ((UimaContextAdmin) context).getResourceManager().getExtensionClassLoader();
+    }
+
+    ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
+    if (contextClassLoader != null) {
+      return contextClassLoader;
+    }
+
+    return null;
+  }
  
   /*
    * (non-Javadoc)
diff --git a/uimaj-core/src/test/java/org/apache/uima/analysis_engine/impl/AnalysisEngineDescription_implTest.java b/uimaj-core/src/test/java/org/apache/uima/analysis_engine/impl/AnalysisEngineDescription_implTest.java
index c0393c1..6f2f866 100644
--- a/uimaj-core/src/test/java/org/apache/uima/analysis_engine/impl/AnalysisEngineDescription_implTest.java
+++ b/uimaj-core/src/test/java/org/apache/uima/analysis_engine/impl/AnalysisEngineDescription_implTest.java
@@ -309,7 +309,6 @@ public class AnalysisEngineDescription_implTest {
     ResourceManager resourceManager = newDefaultResourceManager();
     ConfigurationManager configManager = newConfigurationManager();
     Logger logger = UIMAFramework.getLogger(this.getClass());
-    logger.setResourceManager(resourceManager);
 
     UimaContext uimaContext = UIMAFramework.newUimaContext(logger, resourceManager, configManager);
     final Map<String, Object> p = new HashMap<>();