If you run a java command in process using <java ... failonerror="false"> and do not provide permissions, then the tasks never defines a perm object. Subsequently, Permissions$SM is not installed and if the java program invokes System.exit, it kills the VM instead of being cought and resulting in an ExitException being tossed out of the task execute. However, when failonerror is set to true, if perm==null, a new default Permissions object is defined. The side effect of doing this is that the Permissions object installs a security manager that traps RuntimePermission exitVM checks ant tosses ExitExceptions. So if the java program calls System.exit it doesn't kill the VM. In short, you don't get protection against a VM exit when you don't declare failonerror="true". Since these two concepts are completely distinct, the task should be updated to ensure that the the security manager is either always installed or never installed regardless of the failonerror value. If the choice is to always define a default Permissions when perm is null, then Java.executejava could explicitly trap the ExitException and rethrow it if failonerror=true and the status code is non-zero or smother it otherwise. A build file snippet compares the behavior with and without failonerror: <project ...> <!-- make a TryToExit class that just calls System.exit(1); in it's main: public class TryToExit { public static void main(String[] args) { System.exit(1); } } --> <target name="invoke1"> <echo message="About to invoke with failonerror=false"/> <java classname="TryToExit"/> <!-- VM exit will cause process to abort without ant's consent --> <echo message="TryToExit returned"/> </target> <target name="invoke2"> <echo message="About to invoke with failonerror=true"/> <java classname="TryToExit"/> <!-- VM exit will cause process to abort without ant's consent --> <echo message="TryToExit returned"/> </target> </project> ant invoke1 results in output of: ---- ant invoke1 output --- Using default logger Buildfile: build.xml invoke1: [echo] About to invoke with failonerror=false --------------------------- ---- ant invoke2 output --- Using default logger Buildfile: build.xml invoke2: [echo] About to invoke with failonerror=true BUILD FAILED d:\temp\build.xml:14: Java returned: 1 ---------------------------
The reason the security stuff only went in when failonerror was true was backwards compatibility; once a security manager is in place, things behave differently. There is nothing to stop you adding your own <permissions> entry inside to get the behaviour you want; the failonerror thing is just a shortcut, you indicating the code exits with system.exit. I know this is somewhat unsatisfactory, and am leaving this bug open.
The protection is now also added when failonerror="false".
This is rather unfortunate as it eliminates one of the only (admittedly poor) workarounds for http://www.netbeans.org/issues/show_bug.cgi?id=47645 and makes the bug be triggered on any <java fork="false">. The basic problem is that Ant should not be setting a global security manager without consulting an embedding environment first. I will file a separate bug for that when I get a chance.