Поймать инструкцию по выходу из библиотеки - PullRequest
10 голосов
/ 01 февраля 2011

К моему удивлению и ужасу, я только что натолкнулся на строку System.exit(1); в библиотеке, которую я использую. Я планирую связаться с авторами библиотеки и спросить, что дает, но в то же время есть ли способ предотвратить уничтожение библиотек моим кодом (и, что еще хуже, уничтожение приложения с использованием моего кода)?

Возможно, каким-то образом заставить библиотеку выбросить SecurityException, что, как я вижу, exit(int) может выдать?

Ответы [ 4 ]

13 голосов
/ 01 февраля 2011

Есть только один способ, о котором я знаю, это код SecurityManager, который запрещает использование System.exit.

public class MySecurityMgr extends SecurityManager {
   ... 

   @Override
    public void checkExit(int status) {
            throw new RuntimeException(Integer.toString(status));
    }
}
5 голосов
/ 01 февраля 2011

Я думаю, что ваш единственный выбор (если не считать избиения автора мокрыми полотенцами до тех пор, пока он не переписывает эту чертову штуку) - это изменить байт-код библиотеки.

Симпатичный подход - использовать AspectJ с ткачеством времени загрузкикогда вы загружаете библиотеку, уродливым вариантом является использование инструмента, например asm, для удаления или изменения вызова метода.

Вот аспект AspectJ, который отклоняет вызовы на System.exit():

public aspect SystemExitEvader{

    pointcut systemExitCall() : call(* java.lang.System.exit(*));

    void around() : systemExitCall(){
        System.out.println("Call to System.exit() attempted");
        // note: there is no call to proceed()
    }

}

ОК, я видел другие ответы о SecurityManager'е, и я согласен, что это, вероятно, правильный путь, но я оставлю здесь свой ответ в качестве альтернативы.

4 голосов
/ 01 февраля 2011

Да, вы можете установить SecurityManager, который переопределяет checkExit.

Я нашел это особенно полезным для кода тестирования модулей, чтобы убедиться, что тестируемый код не завершается с 0, что указывает на ложный успех до того, как тесты успеют завершиться.

Это не поможет, если SecurityException в конечном итоге убьет какой-нибудь обычно долгоживущий существенный поток.

3 голосов
/ 01 февраля 2011

Да, администратор безопасности может сделать трюк

// install security manager to avoid System.exit() call from lib
SecurityManager       previousSecurityManager = System.getSecurityManager();
final SecurityManager securityManager         = new SecurityManager() {
    @Override public void checkPermission(final Permission permission) {
      if (permission.getName() != null && permission.getName().startsWith("exitVM")) {
        throw new SecurityException();
      }
    }
  };
System.setSecurityManager(securityManager);

try {
   // Call here your lib code
} catch (SecurityException e) {
  // Say hi to your favorite creator of closed source software that includes System.exit() in his code.
} finally {
  System.setSecurityManager(previousSecurityManager);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...