代码之家  ›  专栏  ›  技术社区  ›  uckelman

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

  •  4
  • uckelman  · 技术社区  · 15 年前

    我们经常从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 这就是我们现在要做的。

    相反,我们希望有一种方法可以在启动时检查升级状态后是否需要重新启动,方法是直接引发此异常并捕获它,或者执行其他检查。(目前,我们甚至不知道是什么触发了这个…)有人知道我们会怎么做吗?

    2 回复  |  直到 15 年前
        1
  •  2
  •   Berin Loritsch    15 年前

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

    我还没有一个Java自动更新需要我重新启动我的机器。如果操作系统从未处于“需要重新启动”状态,那么就没有什么可供您查找和检查的。最好的方法是捕获异常并显示一条好的错误消息。我会把这个问题作为一个bug报告给甲骨文(老兄,很难习惯)。也许将来的更新会正常运行。

        2
  •  0
  •   Grzegorz Oledzki    15 年前

    如果您有一个在异常发生前能够调用某些代码的保证,那么我建议您考虑手动进行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
    
    }