gpt4 book ai didi

c# - 记录 java.sql.SQLException 导致溢出

转载 作者:行者123 更新时间:2023-11-30 16:02:26 26 4
gpt4 key购买 nike

我正在尝试记录来自 IKVM.OpenJDK.Jdbc 程序集的异常。发生的一种异常是 java.sql.SQLException(和子类)。 log4Net 似乎被这个绊倒了,因为 java.sql.SQLException 实现了 IEnumerable 并且它的实现只是返回了它自己。我已经为此逐步完成了 log4net 代码,看起来 log4net 说的是这样的:

"Here is a SQLException to log. Does it contain any information that I should log? Oh, yes it does. There is an IEnumerable, I had better log the stuff inside the IEnumerable. So what is in that IEnumerable? Oh, look it is a SQLException to log. Does it contain any that I should log? Oh, yes it does. There is an IEnumerable, I had better log the stuff inside the IEnumerable. So what is in that IEnumerable? Oh, look it is a SQLException..."

最终我们得到一个StackOverflowException

有没有人遇到过并解决过这个问题?

最小可验证完整示例:

static void Main(string[] args)
{
java.sql.SQLException ex = new java.sql.SQLException();

log4net.Config.BasicConfigurator.Configure();
log4net.ILog logger = log4net.LogManager.GetLogger("foo");
logger.Error("This exception overflows the stack -> ", ex); // Exception here

Console.WriteLine("Finished. Press any key...");
Console.ReadKey();
}

我用来获取正确的 NuGets 以使其编译的 packages.config (NuGet source = https://www.nuget.org/api/v2/ ):

<packages>
<package id="log4net" version="2.0.5" targetFramework="net452" />
<package id="IKVM.OpenJDK.Jdbc" version="7.2.4630.5" targetFramework="net452" />
<!-- The packages below are dependencies from manually getting the packages above. -->
<package id="IKVM.OpenJDK.Charsets" version="7.2.4630.5" targetFramework="net452" />
<package id="IKVM.OpenJDK.Core" version="7.2.4630.5" targetFramework="net452" />
<package id="IKVM.OpenJDK.Misc" version="7.2.4630.5" targetFramework="net452" />
<package id="IKVM.OpenJDK.Naming" version="7.2.4630.5" targetFramework="net452" />
<package id="IKVM.OpenJDK.Remoting" version="7.2.4630.5" targetFramework="net452" />
<package id="IKVM.OpenJDK.Security" version="7.2.4630.5" targetFramework="net452" />
<package id="IKVM.OpenJDK.SwingAWT" version="7.2.4630.5" targetFramework="net452" />
<package id="IKVM.OpenJDK.Text" version="7.2.4630.5" targetFramework="net452" />
<package id="IKVM.OpenJDK.Util" version="7.2.4630.5" targetFramework="net452" />
<package id="IKVM.OpenJDK.XML.API" version="7.2.4630.5" targetFramework="net452" />
<package id="IKVM.Runtime" version="7.2.4630.5" targetFramework="net452" />
</packages>

最佳答案

有一个异常实现 IEnumerable 可以说是一个设计错误——在 .NET 中,一般情况下这是通过 Exception.InnerExceptionSqlException 实现的。 Errors 特别针对数据库错误。然而,提交错误报告可能对您没有好处,因为 IKVM 的目标是在 .NET 中实现 Java,因此它会想要坚持其根源。

使用 log4net 提交错误报告有更多的成功机会,但不会更多,因为以完全通用的方式处理它需要在枚举中进行循环检测,这是一个巨大的痛苦。

幸运的是,有一个更简单的解决方法; log4net 是高度可定制的,通过使用自定义对象渲染器,我们可以随心所欲地处理这些异常。由于可枚举异常的奇怪之处似乎仅限于 IKVM,我们可能可以将其特定于 Throwable:

class ThrowableRenderer : log4net.ObjectRenderer.IObjectRenderer {
private readonly IObjectRenderer fallback;
public ThrowableRenderer(RendererMap rendererMap) {
this.fallback = rendererMap.Get(typeof(Throwable));
}

public void RenderObject(RendererMap rendererMap, object obj, TextWriter writer) {
var filteredEnumerable = (obj as IEnumerable)?.Cast<object>().Skip(1);
if (filteredEnumerable != null) {
rendererMap.FindAndRender(obj.ToString(), writer);
if (filteredEnumerable.Any()) {
writer.WriteLine();
rendererMap.FindAndRender(filteredEnumerable, writer);
}
} else {
fallback.RenderObject(rendererMap, obj, writer);
}
}
}

然后像这样配置自定义渲染器:

var rendererMap = log4net.LogManager.GetRepository().RendererMap;
rendererMap.Put(typeof(Throwable), new ThrowableRenderer(rendererMap));

在上面的实现中,我自定义了 Throwable 的渲染,首先将 Throwable 本身渲染为一个平面对象,然后是链中的任何嵌套异常,但是不是第一个异常(exception)本身。您可能希望进一步自定义它,因为与标准的 Exception 不同,Throwable.ToString() 似乎不包含堆栈跟踪(虽然您可以让 log4net 添加堆栈跟踪到任何错误消息,检索此堆栈跟踪要慢得多),但这演示了通过回避默认呈现来避免堆栈溢出的基本思想。

关于c# - 记录 java.sql.SQLException 导致溢出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37596765/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com