我知道编辑这个网站吗?

2014-07-11 - 斐济不会退出!

##介绍

releasing ImageJ2 into the wild以来,收到了充足的用户反馈。对于那些有reported bugs的人:谢谢!

在所有报告的问题中,有一个问题是最顽固且最难解决的:Fiji bug #805, “Fiji not closing”,俗称“斐济不会放弃!”的问题。(实际上,这个bug的版本在bug#805报告之前就已经存在了,被我们最近一直在跟踪这个bug。)

抄写论文时,我们刚刚发布了ImageJ 2.0.0-rc-9,我们相信它最终在six different attempts to fix it之后解决了这个问题。

标志有两种不同类别的不当行为:

  1. 无法退出。主窗口拒绝消失,从此时起程序基本上无法运行,必须强制关闭。
  2. 进程未终止。 ImageJ 完成其关闭例程并且所有窗口消失,但 Java 进程继续在后台运行,因为 System.exit(0) 从响应调用。

无法退出

引入此类错误是因为we tried to improve upon ImageJ 1.x’s behavior relating to the closing of windows and dialogs。以前的情况是,如果您在Script Editor有未保留更改的选项卡时退出 ImageJ,这些更改将被丢弃,而没有机会先保存。 ImageJ 1.x 批准与其他类型的“默认”窗口(即 ij.ImageJ.main)的行为是在关闭之前立即处理它们,而不发出警告。

为了解决这个问题,我们对WindowManager.closeAllWindows()方法进行了added a callback hook to ImageJ 1.x,这样我们就可以注入额外的行为。然后,我们dispatched a windowClosing event to each remaining window给他们一个选择不被关闭的机会。但事实证明,Java允许窗口取消自己关闭的标准示例将确认关闭(例如,与用户)的想法与在窗口上实际执行关闭/处理的过程混为一谈。事实证明,该方法很脆弱且易于网格局,因此最终我们选择了different approach。使用minor update to the Script Editor,它的窗口现在在退出时仍然提示保存更改(哇!哦),但没有原始方法的脆弱性。

进程未终止

引入第二类问题是因为 ImageJ2 不通过 all Window instances other than ImageWindow, TextWindow or non-Editor PlugInFrame 方法启动 ImageJ。从架构和技术的角度来看,造成这种情况的原因有多种,这超出了本博客文章的范围。但运算说明,ij.ImageJ.main 执行 ImageJ2 启动例程也需要执行的许多操作(但方式不符合),例如处理参数,我们覆盖了其中的大部分内容(除了ij.ImageJ#quit())。默认情况下,ImageJ 1.x在退出时调用System.exit(0),但只要它通过其主要方法启动时,它就会调用。因此,即使在we updated ImageJ2’s quitting routine to lean on ImageJ 1.x as much as possible之后(这解决了我们测试中的许多问题),它仍然不够,因为System.exit(0)从未最终被调用。我们还是通过always setting exitWhenQuitting to true修复了ImageJ旧层中的此差异。

其他并发症

当然,还有其他考虑因素。它需要能够:

  1. 通过 UI 通过基于 ImageJ 1.x 的代码路径 a call setting the exitWhenQuitting flag to true 关闭 ImageJ。 2.通过基于ImageJ2的代码路径disposes the LegacyService and hence ImageJ 1.x以编程方式处理ImageJ,而org.scijava.Context#dispose()

这个代码路径的行为非常不同的两个。在(1)的情况下,会发生一些ImageJ 1.x的退出例程,但会注入额外的逻辑来更好地处理窗口关闭(请参见上面的“无法退出”),并且除了ImageJ 1.x之外还关闭ImageJ2应用程序下面。在(2)的情况下,ImageJ2贯穿其整个外围,包括管理ImageJ 1.x的LegacyService,这意味着ImageJ 1.x作为ImageJ2 执行的部分必须执行 - 所有这些都 potential code path of the ij.IJ#getImage() method

##结论

我们相信我们终于解决了所有这些问题,但正如上面解释所希望的那样,ImageJ 1.x填充了多个代码路径,退出程序也不例外。在ImageJ 1.x库代码中搜索System.exit(0)会得到五个单独的调用位置,令人惊讶的是,其中一个是happen without calling System.exit(0) and without prompting the user to save any changes!在顶部添加ImageJ继承层是一个非常复杂的工作,但我们很自豪地说,可以干净地处理ImageJ2该实例,**占用了整个JVM,这极大地提高了 ImageJ 软件库的可用性。

附:我们added regression tests适用于所有主要场景,甚至包括正确情况下的an integration test for verifying that System.exit(0) is called。 附言“斐济不会放弃”T恤即将上市!:-)