System#exitにまつわるあれこれ

try〜finallyの中にSystem#exit書いた場合ってfinallyは呼ばれるのかね。

結論から言うと、以下のテストケースを流せばわかるのですが、呼ばれません。*1

	@Test
	public void testname() throws Exception {
		try {
			System.exit(0);
		} finally {
			System.out.println("終了ー");
			fail();
		}
	}

さらに、id:kompiroさんからも以下のような情報提供をいただきました!

@setoazusa finally節で呼ばれないみたいですけど、この辺参考にできないですか?http://www.compeople.eu/blog/?p=412

これを参考に、先ほどのテストケースを以下のように書き換えると、

public class ExitTest {

	@Before
	public void setup() {
		System.setSecurityManager(new TestSecurityManager());
	}
	@Test
	public void testname() throws Exception {
		try {
			System.exit(-1);
		} finally {
			System.out.println("終了ー");
		}
	}

	public static class TestSecurityManager extends SecurityManager {
		@Override
		public void checkExit( final int status ) {
			assertThat(status, is(0));
		}
		@Override
		public void checkPermission( final Permission perm ) {
		}
		@Override
		public void checkPermission( final Permission perm, final Object context ) {
		}
	}
}

以下のような結果に。

これを使えばバッチ処理の終了時に処理を挟み込んだり、返り値のassertができたりしますね。あと例外を投げてexitをキャンセルするいたずらにも使えますね^^;覚えておいて損はなさそうです。

*1:exitしているためにJunitのバーが赤にも緑にもならないのはかなりシュール。