Preventing System.exit() from API
You can install a security manager which disables 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 ) ;
}
Edit: Max points out in comments below that
as of Java 6, the permission name is actually "exitVM."+status, e.g. "exitVM.0".
However, the permission exitVM.*
refers to all exit statuses, and exitVM
is retained as a shorthand for exitVM.*
, so the above code still works (see the documentation for RuntimePermission
).
How to prevent calls to System.exit() from terminating the JVM?
Yes, this is possible using a SecurityManager. Try the following
class MySecurityManager extends SecurityManager {
@Override public void checkExit(int status) {
throw new SecurityException();
}
@Override public void checkPermission(Permission perm) {
// Allow other activities by default
}
}
In your class use the following calls:
myMethod() {
//Before running the external Command
MySecurityManager secManager = new MySecurityManager();
System.setSecurityManager(secManager);
try {
invokeExternal();
} catch (SecurityException e) {
//Do something if the external code used System.exit()
}
}
System.exit(0) does not prevent finally being called when have a SecurityManager.checkExit throw an exception
Because exit
was prevented by the ThreadDeath
exception (which is not one you should be throwing yourself btw):
SecurityException - if a security manager exists and its checkExit method doesn't allow exit with the specified status.
https://docs.oracle.com/javase/7/docs/api/java/lang/System.html#exit(int)
Note that you should throw a SecurityException
to prevent exit e.g.:
System.setSecurityManager(new SecurityManager() {
@Override
public void checkExit(int status) {
throw new SecurityException("Not allowed.");
}
});
try {
System.exit(0);
} catch(SecurityException e) {
System.out.println("Exit failed.");
} finally {
System.out.println("I am finally block");
}
System.out.println("Program still running");
Output:
Exit failed.
I am finally block
Program still running
Ignore System.exit() from other class
You can't ignore it per se, but you can prevent it from terminating the JVM via SecurityManager.
Take a look at this question for detailed code example.
Is it safe to use `System.exit()` to stop a java application which has an embed Jetty server?
Sure, you can use System.exit(0)
.
But using the stop method from server would be much more cleaner and prevent you of unexpected errors (e.g. still open request).
Prevent System.exit in a Groovy web console without security policy file
I looked at Groovy's "NoExitSecurityManager" and found it is doing exactly that: disallowing System.exit() ... which is not enough.
My solution was creating my own class "DisallowAllSecurityManager" which extends SecurityManager and disallows everything a script should not need, like write access to the file system or connecting to other hosts, by throwing an SecurityException in each check.. method.
But: You cannot throw an exception in all check.. methods. Here is a list of check.. methods you need to allow:
- checkCreateClassLoader()
- checkMemberAccess()
- checkPackageAccess()
- checkPermission()
- checkPropertyAccess()
- checkRead()
When you want to evaluate your Groovy script you can do it the following way, limiting only the groovy script:
SecurityManager securityManager = System.getSecurityManager();
try {
System.setSecurityManager(new DisallowAllSecurityManager());
Object result = groovyShell.evaluate(expression);
...
} catch (...) {
...
} finally {
System.setSecurityManager(securityManager);
}
Springboot 2.5.1 service doesn't stop on System.exit(0)
Thanks for the thread dump. The problem's caused by a possible bug in Spring Boot where it deadlocks when System.exit(int)
is called while the application context is being refreshed. Thanks for bringing it to our attention.
Until the problem is fixed in Spring Boot you can work around it by setting spring.main.register-shutdown-hook
to false
.
As described in the documentation, SpringApplication.exit
is intended for use in your application's main
method. Your usage of it is rather unusual and you may want to explore taking a different approach.
It looks like you want your application to run in a mode when it migrates the database and then shuts down. Your current approach doesn't appear to restrict what may happen up until the point that the database is migrated. You could take a little more control over that by using a different main @Configuration
class when starting your application. Something like this:
@SpringBootApplication
public class ExampleApplication {
public static void main(String[] args) {
if (args.length > 0 && args[0].equals("migrate")) {
new SpringApplicationBuilder(DatabaseMigration.class).web(WebApplicationType.NONE).run(args);
}
else {
SpringApplication.run(ExampleApplication.class, args);
}
}
@ImportAutoConfiguration(classes = { FlywayAutoConfiguration.class, DataSourceAutoConfiguration.class })
static class DatabaseMigration {
}
}
The above, when started with a --migrate
command line argument, will do just enough to create a DataSource
, run Flyway, and then exit.
Related Topics
Custom JSON Deserialization with Jackson
How to Scroll More Than One Object at the Same Time
Why Hypot() Function Is So Slow
How Does Facebook Add Badge Numbers on App Icon in Android
How to Use Okhttp to Upload a File
Onactivityresult() Not Called in New Nested Fragment API
Deprecated Managedquery() Issue
Java - Ignore Expired Ssl Certificate
Android Change Material Elevation Shadow Color
Difference Between Actionbarsherlock and Actionbar Compatibility
Intellij Fat One Jar Artifact Does Not Generate a Working Output
Getting Java Gui to Open a Webpage in Web Browser
Rxjava Android How to Use the Zip Operator
Asynctask.Executeonexecutor() Before API Level 11
How to Convert Firebase Data to Java Object...