Description
System.exit()
The essence is to notify the JVM to shut down.
Generally speaking. There are two ways System.exit()
to disable this:
- Security Manager
- Security Policy
The essence is the local implementation provided by the JRE, which performs permission inference prior to execution.
Because System.exit()
it is a very violent means. It doesn't matter if you write a small program yourself in Client mode, but there are a lot of problems with multiple programs or multiple threads on the Server.
Underlying source code
1. First look at System.exit()
the source code of the static method:
// System.exit()public static void exit(int status) { Runtime.getRuntime().exit(status);}
It should be said to be very easy, simply invoke the exit method at execution time.
2. Then we look at the instance method at execution time exit
:
// Runtime.exit()public void exit(int status) { SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkExit(status); } Shutdown.exit(status);}
If you have a security manager, let the security Manager perform an checkExit
exit permission check.
If the check does not pass, the security manager throws an exception (this is the Convention!).
)。
The current thread then throws an exception, assuming it is not captured, and the thread exits.
Assuming that no other foreground thread is executing, the JVM will then exit.
3. Shutdown
is one of the following classes in the Java.lang package.
The access permission is default, so we cannot invoke it in the API.
Shutdown.exit () static void exit (int status) {Boolean runmorefinalizers = false; Synchronized (lock) {if (status! = 0) Runfinalizersonexit = false; Switch (state) {case RUNNING:/* Initiate shutdown */state = HOOKS; Break Case HOOKS:/* Stall and halt */break; Case Finalizers:if (Status! = 0) {/* Halt immediately on nonzero status */Halt (status); } else {/* Compatibility with old behavior: * Run more finalizers and then halt */runmorefinalizers = Runfinalizersonexit; } break; }} if (Runmorefinalizers) {runallfinalizers (); Halt (status); } synchronized (Shutdown.class) {/* Synchronize on the class object, causing any other thread * so at Tempts to initiate shutdown to stall indefinitely * * Sequence (); Halt (status); }}
There are some synchronization methods to lock.
The exit logic is called by the halt
method.
// Shutdown.halt()static void halt(int status) { synchronized (haltLock) { halt0(status); }}static native void halt0(int status);
Then it is called the native halt0()
method to let the JVM " suicide ".
Demo sample
The implementation code that uses the security manager is seen in the following example:
1. Define the exception class and inherit fromSecurityException
Exitexception.java
package com.cncounter.security;public class ExitException extends SecurityException { private static final long serialVersionUID = 1L; public final int status; public ExitException(int status) { super("忽略 Exit方法调用!"); this.status = status; }}
2. Define the security manager class, inherit fromSecurityManager
Noexitsecuritymanager.java
package com.cncounter.security;import java.security.Permission;public class NoExitSecurityManager extends SecurityManager { @Override public void checkPermission(Permission perm) { // allow anything. } @Override public void checkPermission(Permission perm, Object context) { // allow anything. } @Override public void checkExit(int status) { super.checkExit(status); throw new ExitException(status); }}
The system directly refuses to exit.
3. Add an auxiliary and test class, you can control the actual use of your own.
Noexithelper.java
package com.cncounter.security;public class NoExitHelper { /** * 设置不同意调用 System.exit(status) * * @throws Exception */ public static void setNoExit() throws Exception { System.setSecurityManager(new NoExitSecurityManager()); } public static void main(String[] args) throws Exception { setNoExit(); testNoExit(); testExit(); testNoExit(); } public static void testNoExit() throws Exception { System.out.println("Printing works"); } public static void testExit() throws Exception { try { System.exit(42); } catch (ExitException e) { // System.out.println("退出的状态码为: " + e.status); } }}
In the middle. A Main method is used to make a simple test. Console output results such as the following:
Printing works退出的状态码为: 42Printing works
Original problem
The original questions such as the following:
I ' ve got a few methods that should call System.exit () on certain inputs. Unfortunately, testing these cases causes JUnit to terminate! Putting the method calls in a new Thread doesn ' t seem to help, since System.exit () terminates the JVM, not just the Curren T thread. Is there any common patterns for dealing and this? For example, can I subsitute a stubs for System.exit ()?
The effect is:
There are some methods that need to be tested, but they are called at certain inputs System.exit()
. This is the cup, and then the JUnit test also withdrew! It is useless to call such a method with a new thread, as it System.exit()
will stop the JVM and not exit the current thread.
Is there a common pattern to deal with such situations?
For example, can I replace the System.exit()
method?
Suggestions such as the following:
Instead of terminating with System.exit (Whatevervalue), why isn't throw an unchecked exception?
In normal use it'll drift all the the-the-last-ditch-the-the-JVM ' s catcher and shut your script down (unless you decide t O catch it somewhere along the, which might be useful someday).
In the JUnit scenario it is caught by the junit framework, which would report that Such-and-such test failed and move Smoothly along to the next.
Translate for example the following:
Calling in a program System.exit(whateverValue)
is a very bad programming habit, so why not throw an unchecked exception (unchecked exception)? Assuming the program does not capture (catch), the thrown exception drifts all the way to the JVM, and then exits the program ( Only the main thread).
In JUnit's test scenario, the exception is caught by the JUnit framework, which then reports that a test execution failed and then continues the next unit test.
The solution, of course, is the previous piece of code. You can also read the following articles to find other solutions.
Articles:
Java: How does the unit test a method that calls System.exit ()?
How to disable API call System.exit () in Java
How to configure the security manager for Tomcat
Date: August 25, 2015
Personnel: Anchor Http://blog.csdn.net/renfufei
Java:System.exit () and security policy