Java-программа завершается, когда заканчивается последний поток без флага демона или когда вы вызываете метод, который выключает виртуальную машину (System.exit (), Runtime.exit (), Runtime.halt () и, возможно, несколько больше).
Все остальное зависит от библиотек, которые вызывают System.exit () (например, JFrame с EXIT_ON_CLOSE).