You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何忽略反射调用中ClassB#main()的System#exit(),避免JVM终止

Absolutely, you can pull this off without rewriting tons of code! Let me break down two reliable approaches depending on your Java version and use case:

Approach 1: Intercept System.exit() with a Custom Security Manager (Java 8 and earlier)

This is the lightest-weight option if you want to keep everything in the same JVM. The idea is to override the default SecurityManager to block calls to System.exit() and throw an exception instead, which you can catch in ClassA to resume execution.

First, create a tiny custom SecurityManager:

class NoExitSecurityManager extends SecurityManager {
    @Override
    public void checkExit(int status) {
        // Throw an exception to stop the exit from happening
        throw new SecurityException("Blocked attempt to exit JVM");
    }
}

Then, wrap your reflection call in ClassA with logic to swap the SecurityManager temporarily:

public class ClassA {
    public static void main(String[] args) {
        // Save the original SecurityManager to restore later
        SecurityManager originalSM = System.getSecurityManager();
        
        try {
            // Activate our custom manager
            System.setSecurityManager(new NoExitSecurityManager());
            
            // Call ClassB's main via reflection as you normally would
            Class<?> classB = Class.forName("ClassB");
            Method mainMethod = classB.getMethod("main", String[].class);
            mainMethod.invoke(null, (Object) new String[]{});
            
        } catch (SecurityException e) {
            // This catches the block from our SecurityManager
            System.out.println("Caught and ignored ClassB's System.exit() call!");
        } catch (Exception e) {
            // Handle other reflection-related errors
            e.printStackTrace();
        } finally {
            // Always restore the original SecurityManager
            System.setSecurityManager(originalSM);
        }
        
        // This line will run even after ClassB tried to exit!
        System.out.println("ClassA's main is still chugging along.");
    }
}
  • Pros:
    • Zero changes needed to ClassB
    • No extra process overhead
    • Runs entirely within the same JVM

Note: For Java 9+, SecurityManager is marked deprecated, but it still works (you'll just get a warning). If you want a deprecation-free option for newer Java versions, go with the next approach.

Approach 2: Run ClassB in a Separate JVM Process (All Java Versions)

If you want complete isolation (and avoid deprecated APIs in Java 9+), spin up a separate JVM process to run ClassB. When ClassB calls System.exit(), it only terminates the child process—not the parent JVM where ClassA is running.

Here's how to implement this in ClassA:

public class ClassA {
    public static void main(String[] args) {
        try {
            // Build a process to run ClassB
            ProcessBuilder pb = new ProcessBuilder(
                // Path to your Java executable
                System.getProperty("java.home") + "/bin/java",
                // The fully qualified name of ClassB
                "ClassB"
            );
            
            // Redirect the child process's output/error to the parent's console (optional)
            pb.inheritIO();
            
            // Start the process and wait for it to finish
            Process childProcess = pb.start();
            int exitCode = childProcess.waitFor();
            
            System.out.println("ClassB exited with code: " + exitCode);
        } catch (IOException | InterruptedException e) {
            e.printStackTrace();
        }
        
        // This line runs regardless of ClassB's exit call
        System.out.println("ClassA's main keeps on running!");
    }
}
  • Pros:
    • Works on every Java version (no deprecation warnings)
    • Complete isolation—ClassB can't crash or terminate ClassA's JVM
    • No changes needed to ClassB
  • Cons:
    • Minor performance overhead from starting a new process
    • Sharing data between ClassA and ClassB requires extra work (like sockets or files) if needed
Final Notes

Both approaches let you ignore ClassB's System.exit() without modifying ClassB itself. Pick the first one if you need same-JVM performance, or the second if you want future-proof, isolated execution.

内容的提问来源于stack exchange,提问作者vkourt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 08:11:12