Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Catch an exit instruction by a library

Tags:

java

exit

To my astonishment and horror, I've just encountered the line System.exit(1); in a library I use. I'm planning on contacting the library's authors and asking what gives, but meanwhile is there any way to prevent the library from killing my code (and worse, killing the application using my code)?

Perhaps somehow force the library to throw a SecurityException, which I see that exit(int) may throw?

like image 397
Oak Avatar asked Feb 01 '11 16:02

Oak


People also ask

What is use of exit () in Java?

exit() method. This method terminates the currently running Java Virtual Machine(JVM). It takes an argument “status code” where a non zero status code indicates abnormal termination.

What is the exit method?

Ex utero intrapartum treatment, also called an EXIT procedure, is a surgical procedure that is used to deliver babies who have airway compression due to cervical teratomas, cystic hygromas or blockage of the airway such as congenital high airway obstruction (CHAOS) syndrome.

What does system exit do in Android?

System.exit() Or in other words, we can say that the system will terminate the application running process and along with it all the associated data — the current activity, app data, etc.


4 Answers

There is only one way I know of, and that is to code a SecurityManager which disallows the use of System.exit.

public class MySecurityMgr extends SecurityManager {
   ... 

   @Override
    public void checkExit(int status) {
            throw new RuntimeException(Integer.toString(status));
    }
}
like image 162
Johan Sjöberg Avatar answered Oct 24 '22 06:10

Johan Sjöberg


I think your only choice (short of whacking the author with wet towels until he rewrites the damn thing) would be to change the library's byte code.

The pretty approach is to use AspectJ with load time weaving when you load the library, the ugly option is to use a tool like asm to either delete or change the method call.

Here's an AspectJ aspect that deflects calls to 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()
    }

}

OK, I've seen the other answers about SecurityManagers and I agree that's probably the way to go, but I'll leave my answer here as an alternative.

like image 42
Sean Patrick Floyd Avatar answered Oct 24 '22 08:10

Sean Patrick Floyd


Yes, you can install a SecurityManager that overrides checkExit.

I've found this particularly useful for unittesting code to make sure that tested code doesn't exit with 0, indicating spurious success before the tests have a chance to run to completion.

This won't help though if the SecurityException ends up killing some normally long-lived essential thread.

like image 23
Mike Samuel Avatar answered Oct 24 '22 08:10

Mike Samuel


yes security manager can do the trick

// 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);
}
like image 22
lweller Avatar answered Oct 24 '22 08:10

lweller