Чи є якась умова, коли нарешті може не працювати в java? Дякую.
Чи є якась умова, коли нарешті може не працювати в java? Дякую.
Відповіді:
з Підручників із Сонця
Примітка: Якщо JVM закривається під час виконання пробного коду, блок остаточного блоку може не виконатись. Так само, якщо потік, який виконує код спробу вилову, перерваний або знищений, остаточний блок може не виконатись, хоча програма в цілому продовжується.
Я не знаю жодних інших способів, нарешті, блок не був би виконаний ...
System.exit вимикає віртуальну машину.
Припиняє працюючий на даний момент віртуальний апарат Java. Аргумент служить кодом статусу; за умовою, ненульовий код статусу вказує на аномальне припинення.
Цей метод викликає
exit
метод у класіRuntime
. Цей метод ніколи не повертається нормально.
try {
System.out.println("hello");
System.exit(0);
}
finally {
System.out.println("bye");
} // try-finally
"до побачення" не друкується у наведеному вище коді.
Просто для розширення того, що сказали інші, все, що не спричинить щось на кшталт виходу JVM, спричинить остаточний блок. Отже, наступний метод:
public static int Stupid() {
try {
return 0;
}
finally {
return 1;
}
}
дивним чином і компілюють, і повернуть 1.
Пов’язані з System.exit, також існують певні типи катастрофічних збоїв, коли нарешті блок може не виконуватись. Якщо у JVM повністю вичерпано пам'ять, він може просто вийти без вилову або, нарешті, відбутися.
Зокрема, я пам’ятаю проект, який ми нерозумно намагалися використати
catch (OutOfMemoryError oome) {
// do stuff
}
Це не спрацювало, оскільки у JVM не залишилося пам'яті для виконання блоку вилову.
try { for (;;); } finally { System.err.println("?"); }
У такому випадку остаточно не буде виконано (якщо не Thread.stop
викликається застаріле або еквівалент, скажімо, через інтерфейс інструментів).
throw
, тоді finally
блок буде виконаний так, як очікувалося. try { throw new ThreadDeath(); } finally { System.err.println("?"); }
Підручник «Сонце» помилково цитується тут у цій темі.
Примітка: Якщо виходи JVM , а спроба зловити або код виконується, то в кінці кінців блок буде не виконувати. Точно так же, якщо потік виконання TRY або зловити код переривається або убитий, нарешті , блок буде не виконувати , навіть якщо додаток в цілому триває.
Якщо ви уважно придивитесь до навчального посібника, щоб остаточно заблокувати, він не говорить "не виконає", але "може не виконати" Ось правильний опис
Примітка: Якщо JVM закривається під час виконання пробного коду, блок остаточного блоку може не виконатись. Так само, якщо потік, який виконує код спробу вилову, перерваний або знищений, остаточний блок може не виконатись, хоча програма в цілому продовжується.
Очевидною причиною такої поведінки є те, що виклик system.exit () обробляється в системній нитці виконання, яка може зайняти час для вимкнення jvm, тим часом планувальник потоків може попросити остаточно виконати. Отже, нарешті, призначено завжди виконувати, але якщо ви вимикаєте jvm, може статися, що jvm відключиться до того, як остаточно буде виконано.
Також якщо всередині try
блоку трапиться тупикова ситуація / вихідний стан .
Ось код, який це демонструє:
public class DeadLocker {
private static class SampleRunnable implements Runnable {
private String threadId;
private Object lock1;
private Object lock2;
public SampleRunnable(String threadId, Object lock1, Object lock2) {
super();
this.threadId = threadId;
this.lock1 = lock1;
this.lock2 = lock2;
}
@Override
public void run() {
try {
synchronized (lock1) {
System.out.println(threadId + " inside lock1");
Thread.sleep(1000);
synchronized (lock2) {
System.out.println(threadId + " inside lock2");
}
}
} catch (Exception e) {
} finally {
System.out.println("finally");
}
}
}
public static void main(String[] args) throws Exception {
Object ob1 = new Object();
Object ob2 = new Object();
Thread t1 = new Thread(new SampleRunnable("t1", ob1, ob2));
Thread t2 = new Thread(new SampleRunnable("t2", ob2, ob1));
t1.start();
t2.start();
}
}
Цей код дає такий вихід:
t1 inside lock1
t2 inside lock1
і "нарешті" ніколи не друкується
Якщо JVM закінчується під час виконання коду спробу вилову, блок нарешті може не виконатись. ( джерело )
Звичайне завершення роботи - це відбувається або тоді, коли останній недемонний потік закінчується АБО, коли Runtime.exit () ( джерело )
Коли потік виходить, JVM виконує інвентаризацію запущених потоків, і якщо єдині залишки, що залишилися, - це демонові потоки, він ініціює впорядковане відключення. Коли JVM зупиняється, залишки будь-яких демонових ниток остаточно блоки не виконуються, стеки не розкручуються, JVM просто виходить. Нитки Daemon слід використовувати рідко, мало обробних операцій можна безпечно відмовитись у будь-який час без очищення. Зокрема, небезпечно використовувати нитки демона для завдань, які можуть виконувати будь-який тип вводу-виводу. Нитки Daemon найкраще зберігати для виконання завдань "ведення домашнього господарства", таких як фонова нитка, яка періодично видаляє закінчені записи з кеша пам'яті. ( джерело )
Останній недемонний потік виходить із прикладу:
public class TestDaemon {
private static Runnable runnable = new Runnable() {
@Override
public void run() {
try {
while (true) {
System.out.println("Is alive");
Thread.sleep(10);
// throw new RuntimeException();
}
} catch (Throwable t) {
t.printStackTrace();
} finally {
System.out.println("This will never be executed.");
}
}
};
public static void main(String[] args) throws InterruptedException {
Thread daemon = new Thread(runnable);
daemon.setDaemon(true);
daemon.start();
Thread.sleep(100);
// daemon.stop();
System.out.println("Last non-daemon thread exits.");
}
}
Вихід:
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Is alive
Last non-daemon thread exits.
Is alive
Is alive
Is alive
Is alive
Is alive
У наступних випадках остаточно блок не буде виконаний: -
System.exit(0)
викликається з try
блоку. try
блоці Можуть бути й інші випадки бахроми, коли нарешті блок не буде виконаний.
Є два способи зупинити остаточне блокування виконання коду:
1. Використовуйте System.exit ();
2. Якщо керування виконанням якимось чином не доходить до спроби блокувати.
Побачити:
public class Main
{
public static void main (String[]args)
{
if(true){
System.out.println("will exceute");
}else{
try{
System.out.println("result = "+5/0);
}catch(ArithmeticException e){
System.out.println("will not exceute");
}finally{
System.out.println("will not exceute");
}
}
}
}
Я натрапив на дуже конкретний випадок, коли нарешті блок не виконується, пов'язаний конкретно з ігровою рамкою.
Я здивовано виявив, що остаточний блок цього коду дії контролера викликається лише після винятку, але ніколи, коли виклик насправді не вдався.
try {
InputStream is = getInputStreamMethod();
renderBinary(is, "out.zip");
catch (Exception e) {
e.printStackTrace();
} finally {
cleanUp();
}
Можливо, нитка припиняється або щось, коли викликається renderBinary (). Я б підозрював, що те ж саме відбувається і з іншими дзвінками render (), але я не підтвердив це.
Я вирішив проблему, перемістивши renderBinary () на спробу / catch. Подальше дослідження показало, що гра надає анотацію @Finally для створення методу, який виконується після виконання дії контролера. Тут заперечення полягає в тому, що це буде викликано після виконання будь-яких дій у контролері, тому це не завжди може бути вдалим вибором.
//If ArithmeticException Occur Inner finally would not be executed
class Temp
{
public static void main(String[] s)
{
try
{
int x = 10/s.length;
System.out.println(x);
try
{
int z[] = new int[s.length];
z[10] = 1000;
}catch(ArrayIndexOutOfBoundsException e)
{
System.out.println(e);
}
finally
{
System.out.println("Inner finally");
}
}
catch(ArithmeticException e)
{
System.out.println(e);
}
finally
{
System.out.println("Outer Finally");
}
System.out.println("Remaining Code");
}
}