Почему объект может быть собран до того, как его метод экземпляра завершит выполнение с помощью GC в Java?

#java #garbage-collection #threadpoolexecutor

#java #сбор мусора #threadpoolexecutor

Вопрос:

Запустив следующий код, вы можете получить java.util.concurrent.RejectedExecutionException исключение.

 /**
 * -Xmx20m -Xms20m
 *
 */
public class SingleThreadPoolTest {

    public static void main(String[] args) {
        for (int i = 0; i < 20000; i  ) {
            newSingleThreadPool();
        }
    }

    private static void newSingleThreadPool() {
        // create a SingleThreadExecutor then submit a task to it
        Executors.newSingleThreadExecutor().submit(new Runnable() {
            @Override
            public void run() {
                byte[] bytes = new byte[1024 * 1024 * 4];
                System.out.println(Thread.currentThread().getName());
            }
        });
    }
}
  

исключение

Проблема здесь в том, что SingleThreadExecutor объект может быть собран с помощью GC, который выполнит его finalize , так что пул потоков будет отключен до submit завершения выполнения его метода экземпляра.

Это казалось нелогичным, это привело бы к ошибкам. Мой вопрос в том, как это могло произойти? Это нормальное поведение GC? И есть ли какой-либо другой язык, на котором GC имеет проблему?


Вот ошибка, о которой сообщается системе ошибок jdk: Executors.newSingleThreadExecutor().submit(runnable) вызывает исключение RejectedExecutionException

Комментарии:

1. Обсуждение в отчете об ошибке не дает ответов на ваши вопросы? Если нет, то что конкретно?

2. @Kayaman Обсуждение сосредоточено на том, как возникает эта конкретная проблема, почему она была разработана таким образом; похоже, что эта ранняя сборка происходит только тогда, когда мы используем поток. Интересно, является ли это общей проблемой языков, в которых есть GC, и есть ли какое-либо возможное решение, позволяющее избежать таких проблем.

3. Вы понимаете, что это особый случай? Они даже упоминают, что добавляемый финализатор является почти «одолжением», потому что люди не закрывали своих исполнителей должным образом. Это также показывает некоторые опасности завершения. Также обсуждаются решения или обходные пути.

4. Но, согласно JLS, JVM разрешено собирать объект, поэтому вопрос заключается в том, следует ли изменять JLS или программисты должны нести ответственность за написание правильного кода. Спорно, какая из них является более сложной задачей 😉