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<>();