2012-04-14 3 views
1

У меня есть следующиеКак я могу «захватить» System.exit (-1) из другого потока?

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

     //custom exception extends SecurityException 
     throw new SystemExitCalledException(); 
    } 
}); 

Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { 
    @Override 
    public void uncaughtException(Thread t, Throwable e) { 
     //never reaches here somehow... 
     //maybe some3rdPartyStaticMethod sets this, too? 
    } 

}); 


try { 
    //this method spawns threads and some call System.exit(). 
    some3rdPartyStaticMethod.invoke(null, new Object[]{args}); 
} catch (SystemExitCalledException e) { 
    //it never reaches here because 
    //SystemExitCalledException is thrown on different thread?? 
    // 
} 

Есть ли способ предотвратить System.exit() вызов порождал поток some3rdPartyStaticMethod от остановки виртуальной машины Java?

+0

Возможно, вы можете использовать «SecurityManager» для замены вызова на «Shutdown.exit» на «SecurityException». –

ответ

2

Вы можете запустить код в отдельном процессе и связаться с ним с помощью RMI. Если код третьей стороны вызывает System.exit и убивает его процесс, ваш процесс может продолжать работать и воссоздавать дочерний процесс, если это необходимо.

Обратите внимание, что есть некоторые оговорки с этим подходом:

  • Эти два процесса не разделяют ту же кучу пространства.
  • Вам необходимо будет маршировать все данные, которые передаются между двумя процессами. Это означает, что данные должны быть сериализованы.
  • Для каждого вызова метода будет значительная накладная. Это может привести к проблемам с производительностью, если вам нужно делать много вызовов в секунду.
+2

+1 Ограничение вашего взаимодействия с кодом, которому вы не доверяете, - это хорошо. Таким образом, у него есть собственный предел кучи. и т. д. –

+2

Конечно, но у Java действительно есть SecurityManager именно для этого, и он избегает всего материала IPC. Не знаю, почему это не работает для него, может быть, файл политики в неправильном положении? – Voo

1

Дать настраиваемую политику SecurityManager должно помочь - я никогда не делал это сам :)

По this post (прокрутите вниз до нижней части):

Однако, когда что-нибудь в VM пытается вызвать System.exit(), VM выходит. Так как это включает в себя жестокое сокращение mvn, нормальный mvn-процесс прерывается. SecurityManager может использоваться для предотвращения вызова кода System.exit(), но никто не упоминает побочные эффекты.

Мой коллега упомянул, что при запуске виртуальной машины вы можете настроить свои политики в общесистемном режиме для каждого пользователя и как системное свойство, и после быстрого теста это позволило решить мою проблему. С тех пор мне удалось выяснить, как установить мою собственную политику из моего кода (до настройки SecurityManager), и это решает мои проблемы.

Я использовал следующий код:

//Setup security to prevent System.exit() 
SecurityManager sm = System.getSecurityManager(); 
URL policy = getClass().getClassLoader().getResource("jsdoc.policy"); 
System.setProperty("java.security.policy", policy.toString()); 
System.setSecurityManager(new JSDocSecurityManager(getLog())); 

С простым, широко открытым, файл политики чтения этого:

grant { 
    permission java.security.AllPermission; 
}; 

Если это работает предполагалось захватить запрос System.exit() и бросить SecurityException вместо