define java securitymanager

java - define - Prevenir System.exit() desde API



java path (4)

Estoy usando una biblioteca de terceros que hace un System.exit() si encuentra excepciones. Estoy usando las API de un contenedor. ¿Hay alguna forma de que pueda evitar la llamada a System.exit() porque hace que se cierre mi aplicación? No puedo descompilar y System.exit() el System.exit() después de eliminar System.exit() debido a muchos otros problemas de licencia. Una vez encontré una respuesta [a alguna otra pregunta que no recuerdo] en stackoverflow que podemos usar SecurityManager en Java para hacer algo como esto.


El uso de SecurityManager para no permitir llamadas de System.exit () no es perfecto, al menos por 2 razones:

  1. Las aplicaciones Java que se ejecutan con y sin SecurityManager habilitado son muy diferentes. Es por eso que debe desactivarse eventualmente, pero no se puede hacer con System.setSecurityManager (null). Esta llamada dará lugar a otra verificación de permiso de seguridad, que inevitablemente fallará, porque el código de la aplicación (subclase SecurityManager) está en la parte superior de la pila de llamadas.

  2. Todas las aplicaciones Java tienen múltiples subprocesos, y otros subprocesos pueden hacer varias cosas entre forbidSystemExitCall () y enableSystemExitCall (). Algunas de estas cosas se pueden proteger con verificaciones de permisos de seguridad, que fallarán por las mismas razones que se describen arriba. Si checkExit () se reemplaza en lugar de [mucho más genérico] checkPermission (), cubrirá la mayoría de los casos, sin embargo.

La única forma (que yo sepa) de resolver esto es otorgar todos los privilegios a la subclase SecurityManager. Es muy probable que requiera que sea cargado por un cargador de clases separado, por ejemplo, cargador de clases bootstrap (nulo).


Hay una publicación en el blog aquí,

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

Básicamente instala un administrador de seguridad que deshabilita System.exit () con código desde here ,

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 ) ; }

Editar : Max señala en los comentarios a continuación que

a partir de Java 6, el nombre del permiso es en realidad "exitVM." + estado, por ejemplo, "exitVM.0".

Sin embargo, el permiso exitVM.* refiere a todos los estados de salida, y exitVM se conserva como una abreviatura de exitVM.* , Por lo que el código anterior sigue funcionando (consulte la documentación de RuntimePermission ).


La muestra del código anterior es parcialmente correcta, pero descubrí que terminó bloqueando el acceso de mi código a los archivos. Para evitar ese problema, escribí mi SecurityManager de manera un poco diferente:

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; } } }

En mi caso, tuve que evitar que una biblioteca de terceros termine la VM. Pero también hubo algunas pruebas de grails que llamaban a System.exit. Entonces, escribí mi código para que solo activara el administrador de seguridad personalizado inmediatamente antes de la llamada a la biblioteca de terceros (no es un evento común) y luego restaure inmediatamente el administrador de seguridad original, si lo hubiera, después.

Todo es un poco feo Idealmente, hubiera preferido eliminar simplemente el código System.exit, pero no tengo acceso al código fuente de la biblioteca de terceros.


Ver mi respuesta a ¿Cómo evitar la operación JFrame EXIT_ON_CLOSE para salir de toda la aplicación? .

Editar 1: la fuente que se vinculó. Demuestra cómo usar un SecurityManager para evitar 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; } }