I have a feeling this has been considered and I might just be articulating
the obvious - but:

As called out in JEP 411, one of the remaining legitimate uses of the
Security Manager is to intercept calls to System.exit. This seems like a
decent use case for the Scope Local mechanism.


    public class Runtime {
        ...
        private final ScopeLocal<IntConsumer> EXIT =
ScopeLocal.newInstance();

        ...

        public void overridingExitBehavior(IntConsumer exit, Runnable run) {
            ScopeLocal.with(EXIT, exit).run(run);
        }

        ...

        public void exit(int status) {
            if (EXIT.isBound()) {
                EXIT.get().accept(status);
            }
            else {
                Shutdown.exit(status);
            }
        }
    }


One of the likely minor benefits in the scope of things, but related to the
parts of the ecosystem I am doodling with so I'll mention it, is that it
would become possible to wrap "naive" cli programs with the ToolProvider
SPI without rewriting their code if this System.out, and System.err all
became reliably configurable.

For instance, Apache Ivy's CLI has a main class that looks like this

https://github.com/apache/ant-ivy/blob/424fa89419147f50a41b4bdc665d8ea92b5da516/src/java/org/apache/ivy/Main.java

    package org.apache.ivy;

    public final class Main {
        ...

        public static void main(String[] args) throws Exception {
            try {
                run(args, true);
                System.exit(0);
            } catch (ParseException ex) {
                System.err.println(ex.getMessage());
                System.exit(1);
            }
        }
     }

Making these otherwise static parts of the system configurable would enable
a third party library to write

    public final class IvyToolProvider implements ToolProvider {
        @Override
        public String name() {
            return "ivy";
        }

        @Override
        public int run(PrintWriter out, PrintWriter err, String... args) {
            var exit = new AtomicInteger(0);
            Runtime.getRuntime().overridingExitBehavior(exit::set, () -> {
                System.overridingOut(out, () -> {
                     System.overridingErr(err, Main::main);
                }
            };
            return exit.get();
        }
    }

Whether that would be enough to make it so that people other than Christian
Stein use the mechanism is anyone's guess, but might be worth a shot.

https://grep.app/search?q=java.util.spi.ToolProvider

Reply via email to