如何在不重新启动的情况下检测JVM是否已升级(在Windows上)?

发布于 2024-09-30 20:00:44 字数 1156 浏览 4 评论 0原文

我们经常从 Windows 用户那里得到以下堆栈跟踪:

java.lang.UnsatisfiedLinkError: sun.awt.image.ImageRepresentation.setBytePixels(IIII[BIILsun/awt/image/ByteComponentRaster;I)V
    at sun.awt.image.ImageRepresentation.setBytePixels(Native Method)
    at sun.awt.image.ImageRepresentation.setPixels(Unknown Source)
    at sun.awt.image.ImageDecoder.setPixels(Unknown Source)
    at sun.awt.image.GifImageDecoder.sendPixels(Unknown Source)
    at sun.awt.image.GifImageDecoder.parseImage(Native Method)
    at sun.awt.image.GifImageDecoder.readImage(Unknown Source)
    at sun.awt.image.GifImageDecoder.produceImage(Unknown Source)
    at sun.awt.image.InputStreamImageSource.doFetch(Unknown Source)
    at sun.awt.image.ImageFetcher.fetchloop(Unknown Source)
    at sun.awt.image.ImageFetcher.run(Unknown Source)

当用户升级 Java,然后尝试在不重新启动的情况下运行我们的应用程序时,就会发生这种情况。显然,升级 Java 需要重新启动计算机(与 Windows 上的其他所有内容一样)才能恢复到可用状态。

这不是我们可以捕获的异常,因为我们的代码都不在调用堆栈中。我们可以处理来自Thread.UncaughtExceptionHandler的异常,这就是我们现在正在做的事情。

相反,我们希望有一种方法可以在启动时检查我们是否处于升级后需要重新启动的状态,可以通过直接引发此异常并捕获它,或者进行其他一些检查。 (目前,我们不知道是什么触发了这个......)有谁知道我们该怎么做?

We frequently get the following stack trace from our Windows users:

java.lang.UnsatisfiedLinkError: sun.awt.image.ImageRepresentation.setBytePixels(IIII[BIILsun/awt/image/ByteComponentRaster;I)V
    at sun.awt.image.ImageRepresentation.setBytePixels(Native Method)
    at sun.awt.image.ImageRepresentation.setPixels(Unknown Source)
    at sun.awt.image.ImageDecoder.setPixels(Unknown Source)
    at sun.awt.image.GifImageDecoder.sendPixels(Unknown Source)
    at sun.awt.image.GifImageDecoder.parseImage(Native Method)
    at sun.awt.image.GifImageDecoder.readImage(Unknown Source)
    at sun.awt.image.GifImageDecoder.produceImage(Unknown Source)
    at sun.awt.image.InputStreamImageSource.doFetch(Unknown Source)
    at sun.awt.image.ImageFetcher.fetchloop(Unknown Source)
    at sun.awt.image.ImageFetcher.run(Unknown Source)

This happens when the user has upgraded Java, and then tries to run our app without rebooting first. Apparently upgrading Java requires (like everything else on Windows) the machine to be rebooted to get things back to a usable state.

This isn't an exception we can catch, since none of our code is in the call stack. We can handle the exception from a Thread.UncaughtExceptionHandler, which is what we're doing now.

We'd like instead to have a way to check at startup whether we're in a need-to-reboot-after-upgrade state, either by causing this exception directly and catching it, or doing some other check. (Presently, we have no idea what even triggers this...) Does anyone know how we might go about that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梦巷 2024-10-07 20:00:44

恐怕你运气不好。可能有一个注册表项让操作系统知道它需要重新启动,但只有在安装程序需要时才会设置。唯一的例外是,如果存在使用 DLL 的代码,否则该代码将被安装程序替换。安装过程将触发操作系统中的“需要重新启动才能完成”对话框。

我还没有遇到 Java 自动更新要求我重新启动机器的情况。如果操作系统从未处于“需要重新启动”状态,则您无法查找和检查任何内容。您能做的最好的事情就是捕获异常并显示一条漂亮的错误消息。我会将此问题作为错误报告给 Oracle(伙计,这很难适应)。也许未来的更新会正常运行。

I'm afraid you are out of luck. There may be a registry entry to let the OS know that it needs to reboot, but that only gets set if the installer requires it. The only other exception is if there is code using a DLL that would otherwise be replaced by the installer. The installation process would trigger the "needs reboot to complete" dialog box from the OS.

I have yet to have a Java automatic update require me to reboot my machine. If the OS is never in a "require reboot" state, there is nothing for you to find and inspect. The best you can do is catch the exception and display a nice error message. I would report this issue as a bug to Oracle (man it'll be hard getting used to that). Maybe future updates will behave properly.

御弟哥哥 2024-10-07 20:00:44

如果您保证能够在异常发生之前调用某些代码,我建议考虑进行手动 java 版本检查。您永远不知道上次升级是否会导致此类崩溃,但您始终可以检查自上次执行以来 Java 版本是否已更改。让我们以简单的方式将其存储在某个地方。

然后,在每次启动期间,如果 Java 版本发生更改,您将显示信息“Java 已更新,我的应用程序可能行为不正常”。建议重新启动和/或停止继续。

像这样的东西:

public static void main(String[] argv) {
  String lastJVM = retrieveJVMversionFromLastExecution();
  String currentJVM = System.getProperty("java.version");
  if (!currentJVM.equals(lastJVM)) {
     throw new RuntimeException("New JVM. Please reboot");
  }  else {
     storeJVMversionPersistently(currentJVM);
  }     

  // ... your normal operation

}

If you have a guarantee to be able to call some code before the exception happens, I would suggest considering doing manual java version check. You never know if the last upgrade would cause such a crash, but you can always check if the Java version has changed since last execution. Let's have it stored somewhere in a simple way.

Then, during each startup if the Java version has changed, you would display information 'Java has been updated and my application may behave improperly. Reboot is suggested' and/or cease to continue.

Something like:

public static void main(String[] argv) {
  String lastJVM = retrieveJVMversionFromLastExecution();
  String currentJVM = System.getProperty("java.version");
  if (!currentJVM.equals(lastJVM)) {
     throw new RuntimeException("New JVM. Please reboot");
  }  else {
     storeJVMversionPersistently(currentJVM);
  }     

  // ... your normal operation

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文