代码之家  ›  专栏  ›  技术社区  ›  Ky -

java.awt.desktop有问题

  •  4
  • Ky -  · 技术社区  · 14 年前

    我的程序中有一个按钮,当按下它时,应该会把你带到我的wiki页面。我使用以下行来完成此操作:

    java.awt.Desktop.getDesktop().browse(new java.net.URI("http://supuh.wikia.com/wiki/BHT"));
    

    问题是,无论运行程序的环境如何,我总是会得到以下错误:

    java.security.AccessControlException: access denied (java.awt.AWTPermission showWindowWithoutWarningBanner)
    

    有人知道我怎么修这个吗?注意,这只在一个程序中有效。我制作的任何其他程序都可以使用相同的方法,没有问题。

    出口挂钩


    在我的程序开始时,这个钩子被添加了。没有它程序运行正常…

    System.setSecurityManager(new SecurityManager()
    {
      @Override
      public void checkExit(int status)
      {
        closeFile(status);
      }
    });
    

    这个钩子是需要的,但是 browse(URI uri) 有问题的方法不适用于它。解决?

    2 回复  |  直到 14 年前
        1
  •  7
  •   Bozho    14 年前

    这意味着您使用的是安全管理器:

    SecurityException -如果存在安全管理器,并且它拒绝AWT权限(“SkyWistWOWE OutalRunBand”)权限,或者调用线程不允许创建子进程;并且不从Applet或Java Web启动应用程序中调用

    如果这是一个applet,或者一个Java Web启动应用程序,就签上你的JAR。

    更新 添加安全管理器以检测程序退出 错误的 . 有多种方法可以正确地做到这一点。在你的情况下,我想这是最合适的:

    Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
          @Override
          public void run() {
             closeFile();
          }
    ));
    

    Swing特定的解决方案是:

    • 如果不需要执行额外操作,请使用 frame.setDefaultCloseAction(Frame.EXIT_ON_CLOSE)

    • 使用 addWindowStateListener 并检查 WindowEvent.WINDOW_CLOSED

    也就是说,两个注意事项:

    • 不能长时间保存打开的文件。使用 try/catch/finally 在需要时打开和关闭它们。

    • 如果您在某个时刻确实需要安全管理器,请确保重写 SecurityManager 这将检查是否可以打开链接。(不会告诉你是哪一个,这样你就不会想跳到这个解决方案上来,这是错误的)

    总而言之,我想 setDefaultActionOnClose ,并在完成读/写后立即关闭每个文件。

    更新2: 当你链接到你最初的问题描述你到底想要达到什么目标后,事情就发生了一些变化。你 试图阻止退出,所以您需要 安全管理员 . 这使得您可以重写 checkPermission 方法,并且不在其中执行任何操作(即不引发异常),至少在检查这些权限时(调用浏览时检查这些权限):

    • new AWTPermission("showWindowWithoutWarningBanner")
    • new FilePermission("<<ALL FILES>>", SecurityConstants.FILE_EXECUTE_ACTION)

    更新3 下面是如何准确地重写该方法:

    @Override
    public void checkPermission(Permission permission) {
       if (permission instanceof AWTPermission) {
           if (permission.getName().equals("showWindowWithoutWarningBanner")) {
               return;
           }
       }
    
       if (permission instanceof FilePermission) {
           if (permission.getActions().equalsIgnoreCase("execute")) {
              return;
           }
       }
    
       java.security.AccessController.checkPermission(permission);
    }
    

    (您可以不使用外部IF-S)

    更新4 只有在您授予程序权限的情况下,上述方法才有效。否则,对于JVM来说,覆盖安全管理器是不允许被取消特权的,这是一种没有很好文档记录的行为。看看 this report -这些评论说明了如何解决问题。

    为了让你的生活更简单,你可以 @Override public void checkPermission(..) 方法体为空。

        2
  •  0
  •   Aaron Digulla    14 年前

    而不是用你自己的 SecurityManager ,安装一个关闭挂钩:

    Runnable runnable = new Runnable() {
        closeFile(status);
    }
    
    Runtime.getRuntime().addShutdownHook(new Thread (runnable, "Close file"));