为了账号安全,请及时绑定邮箱和手机立即绑定

从API阻止System.exit()

/ 猿问

从API阻止System.exit()

慕仰8121524 2019-10-21 11:04:18

我使用的第三方库System.exit()在遇到异常时会执行a 。我从罐子里使用API。无论如何,System.exit()由于它导致我的应用程序关闭,我可以阻止该调用吗?System.exit()由于其他许多许可问题,删除后我无法反编译和重新编译jar 。我曾经在stackoverflow中遇到一个[我不记得的其他问题]的答案,我们可以使用SecurityManagerJava来做这样的事情。



查看完整描述

3 回答

?
UYOU

这里有一篇博客文章,


http://jroller.com/ethdsy/entry/disabling_system_exit


基本上,它会安装一个安全管理器,该安全管理器会使用此处的代码禁用System.exit(),


  private static class ExitTrappedException extends SecurityException { }


  private static void forbidSystemExitCall() {

    final SecurityManager securityManager = new SecurityManager() {

      public void checkPermission( Permission permission ) {

        if( "exitVM".equals( permission.getName() ) ) {

          throw new ExitTrappedException() ;

        }

      }

    } ;

    System.setSecurityManager( securityManager ) ;

  }


  private static void enableSystemExitCall() {

    System.setSecurityManager( null ) ;

  }

编辑:最大指出以下评论


从Java 6开始,权限名称实际上是“ exitVM。” +状态,例如“ exitVM.0”。


但是,该权限exitVM.*指的是所有退出状态,并且exitVM保留为的简写形式exitVM.*,因此上述代码仍然有效(请参阅参考资料中的RuntimePermission)。


查看完整回答
反对 回复 2019-10-21
?
30秒到达战场

请参阅我对如何避免JFrame EXIT_ON_CLOSE操作退出整个应用程序的答复?。


编辑1:链接的源。演示如何使用SecurityManager来预防System.exit(n)。


import java.awt.*;

import java.awt.event.*;

import java.security.Permission;


/** NoExit demonstrates how to prevent 'child'

applications from ending the VM with a call

to System.exit(0).

@author Andrew Thompson */

public class NoExit extends Frame implements ActionListener {


  Button frameLaunch = new Button("Frame"),

     exitLaunch = new Button("Exit");


  /** Stores a reference to the original security manager. */

  ExitManager sm;


  public NoExit() {

     super("Launcher Application");


     sm = new ExitManager( System.getSecurityManager() );

     System.setSecurityManager(sm);


     setLayout(new GridLayout(0,1));


     frameLaunch.addActionListener(this);

     exitLaunch.addActionListener(this);


     add( frameLaunch );

     add( exitLaunch );


     pack();

     setSize( getPreferredSize() );

  }


  public void actionPerformed(ActionEvent ae) {

     if ( ae.getSource()==frameLaunch ) {

        TargetFrame tf = new TargetFrame();

     } else {

        // change back to the standard SM that allows exit.

        System.setSecurityManager(

           sm.getOriginalSecurityManager() );

        // exit the VM when *we* want

        System.exit(0);

     }

  }


  public static void main(String[] args) {

     NoExit ne = new NoExit();

     ne.setVisible(true);

  }

}


/** This example frame attempts to System.exit(0)

on closing, we must prevent it from doing so. */

class TargetFrame extends Frame {

  static int x=0, y=0;


  TargetFrame() {

     super("Close Me!");

     add(new Label("Hi!"));


     addWindowListener( new WindowAdapter() {

        public void windowClosing(WindowEvent we) {

           System.out.println("Bye!");

           System.exit(0);

        }

     });


     pack();

     setSize( getPreferredSize() );

     setLocation(++x*10,++y*10);

     setVisible(true);

  }

}


/** Our custom ExitManager does not allow the VM

to exit, but does allow itself to be replaced by

the original security manager.

@author Andrew Thompson */

class ExitManager extends SecurityManager {


  SecurityManager original;


  ExitManager(SecurityManager original) {

     this.original = original;

  }


  /** Deny permission to exit the VM. */

   public void checkExit(int status) {

     throw( new SecurityException() );

  }


  /** Allow this security manager to be replaced,

  if fact, allow pretty much everything. */

  public void checkPermission(Permission perm) {

  }


  public SecurityManager getOriginalSecurityManager() {

     return original;

  }

}


查看完整回答
反对 回复 2019-10-21
?
慕容森

先前的代码示例部分正确,但是我发现它最终阻止了我的代码对文件的访问。为了解决这个问题,我写了一些不同的SecurityManager:


public class MySecurityManager extends SecurityManager {


private SecurityManager baseSecurityManager;


public MySecurityManager(SecurityManager baseSecurityManager) {

    this.baseSecurityManager = baseSecurityManager;

}


@Override

public void checkPermission(Permission permission) {

    if (permission.getName().startsWith("exitVM")) {

        throw new SecurityException("System exit not allowed");

    }

    if (baseSecurityManager != null) {

        baseSecurityManager.checkPermission(permission);

    } else {

        return;

    }

}


}

就我而言,我需要防止第三方库终止VM。但是也有一些grails测试调用System.exit。因此,我编写了代码,以使其仅在调用第三方库之前立即激活了自定义安全管理器(不是常见事件),然后立即恢复了原始安全管理器(如果有)。


有点丑陋。理想情况下,我宁愿只删除System.exit代码,但不能访问第三方库的源代码。


查看完整回答
反对 回复 2019-10-21

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信