问题输入:
- 我有一个基于 64 位 Windows 的桌面应用程序,使用 Java 使用 SWT 开发。
- 使用任务管理器我可以看到 GUI 句柄的数量:aprox。 900 个用户对象和 1700 个GDI 对象。在应用程序的整个运行过程中,这些数字保持在同一水平。
- 我的系统上允许的用户对象和 GDI 对象的最大数量均为 10k。我通过查看 GDIProcessHandleQuota 和 USERProcessHandleQuota 注册表找到了答案。
与当前用户正常运行应用程序(一次或并行多次)不会产生任何类型的问题。一切都按预期运行。
问题:
当我尝试在作为服务启动的 Jenkins 中运行应用程序时,出现问题(SWTError:没有更多句柄)。我知道在 Windows 服务中,应用程序不显示任何 GUI,但它仍然“获取”用户对象和 GDI 对象。几秒钟后,我不断收到各种“不再有相关的句柄”错误,如下所示:
11:08:40.315 WARN - org.eclipse.swt.SWTError: No more handles
11:08:40.315 WARN - org.eclipse.swt.SWT.error(SWT.java:4559)
11:08:40.315 WARN - org.eclipse.swt.SWT.error(SWT.java:4448)
11:08:40.315 WARN - org.eclipse.swt.SWT.error(SWT.java:4419)
11:08:40.315 WARN - org.eclipse.swt.widgets.Widget.error(Widget.java:482)
11:08:40.315 WARN - org.eclipse.swt.widgets.Control.createHandle(Control.java:718)
11:08:40.316 WARN - org.eclipse.swt.widgets.Composite.createHandle(Composite.java:292)
11:08:40.316 WARN - org.eclipse.swt.widgets.Decorations.createHandle(Decorations.java:430)
11:08:40.316 WARN - org.eclipse.swt.widgets.Shell.createHandle(Shell.java:593)
11:08:40.316 WARN - org.eclipse.swt.widgets.Control.createWidget(Control.java:758)
11:08:40.316 WARN - org.eclipse.swt.widgets.Scrollable.createWidget(Scrollable.java:151)
11:08:40.316 WARN - org.eclipse.swt.widgets.Decorations.createWidget(Decorations.java:439)
11:08:40.316 WARN - org.eclipse.swt.widgets.Shell.<init>(Shell.java:300)
11:08:40.316 WARN - org.eclipse.swt.widgets.Shell.<init>(Shell.java:379)
11:08:40.317 WARN - org.eclipse.jface.window.Window.createShell(Window.java:482)
11:08:40.317 WARN - org.eclipse.jface.window.Window.create(Window.java:425)
11:08:40.317 WARN - org.eclipse.jface.dialogs.Dialog.create(Dialog.java:1096)
11:08:40.317 WARN - org.eclipse.jface.window.Window.open(Window.java:783)
11:08:40.317 WARN - org.eclipse.jface.dialogs.MessageDialog.open(MessageDialog.java:396)
11:08:40.317 WARN - org.eclipse.jface.dialogs.MessageDialog.open(MessageDialog.java:424)
11:08:40.317 WARN - org.eclipse.jface.dialogs.MessageDialog.openError(MessageDialog.java:520)
11:08:40.317 WARN - app.widget.ui.WidgetTab.openError_aroundBody0(WidgetTab.java:605)
11:08:40.317 WARN - app.widget.ui.WidgetTab$AjcClosure1.run(WidgetTab.java:1)
11:08:40.317 WARN - org.aspectj.runtime.reflect.JoinPointImpl.proceed(JoinPointImpl.java:167)
11:08:40.317 WARN - util.aspects.MessageDialogAspect.proceedToDialog(MessageDialogAspect.java:221)
11:08:40.317 WARN - util.aspects.MessageDialogAspect.handleMessage(MessageDialogAspect.java:90)
11:08:40.317 WARN - util.aspects.MessageDialogAspect.ajc$inlineAccessMethod$util_aspects_MessageDialogAspect$util_aspects_MessageDialogAspect$handleMessage(MessageDialogAspect.java:1)
11:08:40.317 WARN - util.aspects.MessageDialogAspect.openError(MessageDialogAspect.java:50)
11:08:40.318 WARN - app.widget.ui.WidgetTab.displayWidget(WidgetTab.java:605)
迄今为止的调查:
- 我使用了 TeSTLimit ( https://learn.microsoft.com/en-us/sysinternals/downloads/testlimit ) 工具,但它不是很有结论,所以我创建了自己的小型 Windows 测试应用程序,它创建了尽可能多的窗口和画笔 (< em>CreateWindiowsEx 和 CreateSolidBrush)之后它会打印最后一个错误。
使用当前用户运行测试应用程序,可以分别生成接近 10000 个用户对象和 GDI 对象的最大值。最后一个错误:(代码 1158)当前进程已使用窗口管理器对象的所有系统句柄限额。
在 Jenkins 中运行测试应用程序:窗口的创建停止在 1700 左右(用户对象),而画笔的创建达到最大值 10000(GDI 对象),两者都出现相同的错误:(代码 8)< em>没有足够的内存资源来处理此命令。
问题/期望:
- 调查使我发现了超出最大对象数量时预期的限制之外的其他限制,因为用户对象的创建在达到最大数量之前就中断了。
- Windows 服务中的 GUI 句柄是否存在任何“隐藏”限制?除了“ Material ”部分中发布的那些伪文档之外,我找不到任何与此相关的文档。
- 为什么测试应用在由用户启动时“抓取”10k 个用户对象,而在由 SYSTEM 服务启动时仅“抓取”1700 个?
- 我希望发现该服务存在限制,但我现在无法弄清楚。有什么想法吗?谢谢!
Material :
- https://blogs.technet.microsoft.com/markrussinovich/2009/09/29/pushing-the-limits-of-windows-handles/
- https://forum.solidworks.com/thread/214732
更新
关于错误日志,正如我上面所说的“不断收到所有‘不再有相关处理’错误”。我只是放置了另一条日志消息,以免被第一个日志中出现的 MessageDialog.openError 混淆。
12:01:14.661 ERROR - org.eclipse.swt.SWTError: Item not added
12:01:14.661 ERROR - at org.eclipse.swt.SWT.error(SWT.java:4559)
12:01:14.661 ERROR - at org.eclipse.swt.SWT.error(SWT.java:4448)
12:01:14.661 ERROR - at org.eclipse.swt.SWT.error(SWT.java:4419)
12:01:14.661 ERROR - at org.eclipse.swt.widgets.Widget.error(Widget.java:482)
12:01:14.662 ERROR - at org.eclipse.swt.widgets.Menu.createItem(Menu.java:533)
12:01:14.662 ERROR - at org.eclipse.swt.widgets.MenuItem.<init>(MenuItem.java:134)
12:01:14.662 ERROR - at org.eclipse.jface.action.ActionContributionItem.fill(ActionContributionItem.java:257)
12:01:14.662 ERROR - at org.eclipse.jface.action.MenuManager.doItemFill(MenuManager.java:728)
12:01:14.662 ERROR - at org.eclipse.jface.action.MenuManager.update(MenuManager.java:810)
12:01:14.662 ERROR - at org.eclipse.jface.action.MenuManager.updateAll(MenuManager.java:932)
12:01:14.662 ERROR - at org.eclipse.jface.action.MenuManager.update(MenuManager.java:830)
12:01:14.663 ERROR - at org.eclipse.jface.window.ApplicationWindow.createTrimWidgets(ApplicationWindow.java:355)
12:01:14.664 ERROR - at org.eclipse.jface.window.ApplicationWindow.configureShell(ApplicationWindow.java:341)
12:01:14.664 ERROR - at app.ui.Gui.configureShell(Gui.java:544)
12:01:14.664 ERROR - at org.eclipse.jface.window.Window.createShell(Window.java:493)
12:01:14.664 ERROR - at org.eclipse.jface.window.Window.create(Window.java:425)
12:01:14.664 ERROR - at app.ui.Gui.create(Gui.java:584)
12:01:14.664 ERROR - at app.ui.Gui.open(Gui.java:275)
12:01:14.665 ERROR - at app.GuiController.init(GuiController.java:411)
12:01:14.665 ERROR - at app.GuiController.main(GuiController.java:260)
12:01:14.783 ERROR - Exception in thread "SWT Thread"
最佳答案
正如 @greg-449 所指出的,您的进程正在尝试从 Windows 服务创建 GUI 控件(错误消息 Shell)。默认情况下,Windows 服务不允许与桌面交互,您必须设置 SERVICE_INTERACTIVE_PROCESS 服务标志才能使它们能够这样做,请检查 Windows documentation了解详情。但我的猜测是,您不打算从 Jenkins 任务显示 UI,因此您必须调试应用程序尝试显示错误对话框的原因。
在这种情况下,消息不再有句柄
具有误导性。
查看 Control.createHandle
的 SWT 源代码:
void createHandle () {
long hwndParent = widgetParent ();
handle = OS.CreateWindowEx (
widgetExtStyle (),
windowClass (),
null,
widgetStyle (),
OS.CW_USEDEFAULT, 0, OS.CW_USEDEFAULT, 0,
hwndParent,
0,
OS.GetModuleHandle (null),
widgetCreateStruct ());
if (handle == 0) error (SWT.ERROR_NO_HANDLES);
...
如您所见,当 OS.CreateWindowEx
失败并返回零时,在任何情况下都会引发 SWT.ERROR_NO_HANDLES
错误 - 在您的情况下,因为运行非-互动服务。没有实际检查用户或 GDI 句柄限制是否已用完。
关于java - Windows Jenkins 服务 org.eclipse.swt.SWTError : No more handles,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59500258/