Принудительное явное удаление объекта Java - PullRequest
14 голосов
/ 01 февраля 2010

Я работаю на сервере Java, который обрабатывает много очень плотного трафика. Сервер принимает пакеты от клиентов (часто много мегабайт) и пересылает их другим клиентам. Сервер никогда явно не хранит какие-либо входящие / исходящие пакеты. Тем не менее, сервер постоянно сталкивается с OutOfMemoryException исключениями.

Я добавил System.gc() в компонент передачи сообщений сервера, надеясь, что память будет освобождена. Кроме того, я установил размер кучи JVM в гигабайт. Я все еще получаю столько же исключений.

Итак, мой вопрос таков: как я могу убедиться, что мегабайтные сообщения не помещаются в очередь на неопределенный срок (несмотря на то, что они не нужны)? Есть ли способ для меня, чтобы вызвать "удалить" на этих объектах, чтобы гарантировать, что они не используют мое пространство кучи?

        try
        {
           while (true)
            {
               int r = generator.nextInt(100);//generate a random number between 0 and 100
                Object o =readFromServer.readObject();
                sum++;
                // if the random number is larger than the drop rate, send the object to client, else
                //it will be dropped
                if (r > dropRate)
                {
                    writeToClient.writeObject(o);
                    writeToClient.flush();
                    numOfSend++;
                    System.out.printf("No. %d send\n",sum);
                }//if

            }//while
        }//try

Ответы [ 14 ]

0 голосов
/ 01 февраля 2010

Если ваш сервер работает в течение хотя бы нескольких минут, прежде чем он умрет, вы можете попробовать запустить его в Visual VM. Вы, по крайней мере, могли бы получить лучшее представление о том, как быстро растет куча и какие в ней объекты.

0 голосов
/ 01 февраля 2010

Вы упоминаете, что вам явно нужен весь полученный пакет, прежде чем вы сможете его отправить?Ну, это не значит, что вам нужно хранить все это в памяти, не так ли?Является ли возможным архитектурное изменение для сохранения полученных пакетов во внешнем хранилище (может быть, ram-диск или БД, если даже SSD работает слишком медленно), а затем направляет их напрямую получателю, не загружая их полностью в память?

0 голосов
/ 01 февраля 2010

просто для добавления ко всем этим предыдущим ответам: System.gc () не является командой для JVM для запуска сборки мусора ... это кроткое направление и не гарантирует, что что-либо произойдет. Спецификация JVM оставляет поставщикам возможность решать, что нужно делать с вызовами gc. Продавцы могут даже вообще ничего не делать!

0 голосов
/ 01 февраля 2010

Ручной запуск System.gc не является хорошим ответом, как другие опубликовали здесь.Он не гарантированно работает, и он запускает полный gc, который может зависать на вашем сервере в течение длительного времени, пока он работает (> 1 секунды, если вы даете серверу 1 ГБ ОЗУ, я видел несколько минутдлинные паузы на больших системах).Вы можете настроить свой gc, что, безусловно, поможет, но не полностью решит проблему.

Если вы читаете объекты из одного потока, а затем записываете их в другой, то есть момент, когда выдержа весь объект в памяти.Если эти объекты, как вы говорите, большие, то это может стать вашей проблемой.Попробуйте переписать свой ввод-вывод, чтобы вы читали байты из 1 потока и записывали их в другой, даже не удерживая явно весь объект (хотя я не могу понять, как это будет работать с сериализацией / десериализацией объекта, если вам нужно проверить / проверить объекты).

...