java - Windows Jenkins 服务 org.eclipse.swt.SWTError : No more handles

标签 java windows resources swt gdi

问题输入:

  • 我有一个基于 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>CreateWindiowsExCreateSolidBrush)之后它会打印最后一个错误。
  • 使用当前用户运行测试应用程序,可以分别生成接近 10000 个用户对象和 GDI 对象的最大值。最后一个错误:(代码 1158)当前进程已使用窗口管理器对象的所有系统句柄限额。

  • 在 Jenkins 中运行测试应用程序:窗口的创建停止在 1700 左右(用户对象),而画笔的创建达到最大值 10000(GDI 对象),两者都出现相同的错误:(代码 8)< em>没有足够的内存资源来处理此命令。

问题/期望:

  • 调查使我发现了超出最大对象数量时预期的限制之外的其他限制,因为用户对象的创建在达到最大数量之前就中断了。
  • Windows 服务中的 GUI 句柄是否存在任何“隐藏”限制?除了“ Material ”部分中发布的那些伪文档之外,我找不到任何与此相关的文档。
  • 为什么测试应用在由用户启动时“抓取”10k 个用户对象,而在由 SYSTEM 服务启动时仅“抓取”1700 个?
  • 我希望发现该服务存在限制,但我现在无法弄清楚。有什么想法吗?谢谢!

Material :

更新

关于错误日志,正如我上面所说的“不断收到所有‘不再有相关处理’错误”。我只是放置了另一条日志消息,以免被第一个日志中出现的 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/

相关文章:

java - 如何监听端口上传入的数据包?

java - 当分隔符移动到 ComponentListener 内时,JSplitPane 会阻止 PropertyChangeEvent

c# - 如何从代码隐藏文件中的合并 ResourceDictionary 获取资源?

java - 将图像插入 vaadin 网格

java - Android AppUpdateManager 未初始化自动更新

c++ - 用于构建 boost : "don' t know how to make <e>stage"的“阶段”参数

windows - 在哪里可以找到在 Windows 上运行的 Emacs 的 .emacs 文件?

c - 如何将反汇编的C代码划分为函数?

resources - 编写国际象棋引擎有哪些好的资源?

java - 使用 Java 8 创建 int 事件映射