Это действительно очень странная ошибка.Когда вы посмотрите на источник AbstractObjectFactory.GetObjectInternal
, вы увидите следующую структуру:
[ThreadStatic]
private int nestingCount;
protected object GetObjectInternal(...)
{
const int INDENT = 3;
bool hasErrors = false;
try
{
nestingCount++;
if (log.IsDebugEnabled)
{
log.Debug("msg" +
new String(' ', nestingCount * INDENT));
}
// More code: Calls self recursively.
}
catch
{
nestingCount--;
hasErrors = true;
if (log.IsErrorEnabled)
{
log.Error("msg" +
new String(' ', nestingCount * INDENT));
}
}
finally
{
if (!hasErrors)
{
nestingCount--;
if (log.IsDebugEnabled)
{
log.Debug("msg" +
new String(' ', nestingCount * INDENT));
}
}
}
}
Исключение, которое вы видите, должно быть вызвано одним из трех вызовов new String(' ', nestingCount * INDENT)
.Этот конкретный вызов конструктора string
генерируется, когда предоставленное значение является отрицательным.Поскольку INDENT
является константой, nestingCount
в этом случае должно иметь отрицательное значение.nestingCount
является потоковой статической переменной.Статические переменные потока всегда инициализируются со значением по умолчанию (в данном случае 0) и не могут зависеть от других потоков.Более того, nestingCount
никогда не используется вне этого метода.
Поскольку nestingCount
является потоково-статическим и используется только в этом методе, трудно представить сценарий, когда nestingCount
может стать отрицательным.Возможно, в случае асинхронного (ThreadAbort) исключения, но даже это мне сложно представить.Другой вариант заключается в том, что переменная-статическая переменная изменяется кем-то другим, используя отражение.
Но главный вопрос: как решить эту проблему?
Решение:
Есть только одна вещь, о которой я могу думать, это переконфигурировать log4net таким образом, чтобы отладочная информация не регистрировалась.При запрете отладочной информации конструктор string(char, int)
, вероятно, больше никогда не будет вызван, что позволит скрыть проблему.Не очень красиво, но, возможно, эффективно.Это может работать, потому что AbstractObjectFactory
регистрирует с использованием переменной log
, которая инициализируется следующим образом:
this.log = LogManager.GetLogger(this.GetType());
Вы можете сделать это, отключив запись отладочной информации в log4net глобально, или - когда выдумаю, что это излишне - настроив log4net на отключение отладочной информации для типа Spring.Objects.Factory.Support.DefaultListableObjectFactory
(экземпляр, который фактически вызывает исключение).
Удачи.