Я "исправил" утечку памяти, но ... как это исправить лучше? - PullRequest
3 голосов
/ 04 августа 2010

Это было очень быстро и самодельно, исправление ошибки .. Это сработало, но я хотел бы найти лучшее понимание и решение.

Это был конструктор классов, генерирующий утечку

final transient  DataInputStream din;
final transient  DataOutputStream dout;
final transient  BufferedReader bin;
final transient  BufferedWriter bout;

NData(Socket sock0) throws IOException
    {
        sock=sock0;
        din= new DataInputStream(sock.getInputStream());
        dout = new DataOutputStream(sock.getOutputStream());
        bin = new BufferedReader(new InputStreamReader(din));
        bout = new BufferedWriter(new OutputStreamWriter(dout));
     //   .. 
    }

Исправление ошибки состояло в том, чтобы изменить его (удалить финал), чтобы позволить мне позже присвоить ноль

transient  DataInputStream din;
transient  DataOutputStream dout;
transient  BufferedReader bin;
transient  BufferedWriter bout;

NData(Socket sock0) throws IOException
    {
        sock=sock0;
        din= new DataInputStream(sock.getInputStream());
        dout = new DataOutputStream(sock.getOutputStream());
        bin = new BufferedReader(new InputStreamReader(din));
        bout = new BufferedWriter(new OutputStreamWriter(dout));
     //   .. 
    } 

 //And to add a "magic" destructor

 void nuller() {
        din=null;
        dout=null;
        bin=null;
        bout=null;
    }

Был метод финиша, который завершил поток, закрыл потоки, поэтому я добавил туда вызов метода "nuller", и утечка памяти ушла.

Почему после завершения потока и закрытия потока он продолжает выделять память в "byte []"? Почему GC не выбрасывает это? (кроме как после этого грязного с нулевым присвоением)

EDIT:

Как Касабланка говорит, что, возможно, объект NData все еще существует, есть

final static ConcurrentHashMap <String,NData>(); 

для того, чтобы в качестве значений были указаны NData, выполняется удаление (ключ), чтобы удалить объект с карты, но ... этого недостаточно.

Удаление из HashMap единственной ссылки на объект будет недостаточно для удаления объекта?

Ответы [ 3 ]

4 голосов
/ 04 августа 2010

Почему после завершения потока и закрытия потока он продолжает выделять память в "byte []"? Почему GC не выбрасывает это?

GC "выбросит" что-то, только когда больше нет ссылок на этот объект. В вашем случае это означает, что что-то все еще содержит ссылку на объект NData. Вызывая метод nuller вручную, вы просто освобождаете ссылки на переменные-члены (din, dout и т. Д.), Но объект NData, вероятно, все еще лежит. Вам нужно поискать в другом месте, чтобы узнать, кто использует этот объект и убедиться, что эта ссылка очищена.

Обновление: Как именно вы пришли к выводу, что произошла утечка памяти? GC запускается только периодически, поэтому не гарантируется немедленное освобождение объектов. Вы можете попробовать позвонить System.gc(), чтобы запустить GC. Кроме того, ConcurrentHashMap (с которым я не знаком) может кэшировать ссылки для параллелизма, и возможно, что они не освобождаются сразу после вызова remove.

3 голосов
/ 04 августа 2010

Вы должны сделать дамп кучи после очистки объекта NData. Затем найдите объект NData в куче (потому что, по вашему описанию, кто-то по-прежнему твердо на него ссылается!). Затем выясните, как этот объект доступен из корневого набора .

Недавно мне пришлось это сделать, и я нашел процесс удобным с помощью этих инструментов:

VisualVM , для получения дампа кучи.

Eclipse Memory Analyzer (я использовал его автономно) для анализа кучи, в частности, поиска путей из корневого набора.

Второй в настоящее время значительно более продвинутый, чем первый, но графический интерфейс первого очень удобен (если он также был полон!).

1 голос
/ 04 августа 2010

В вашем nuller вызовите bin.close () и bout.close (), которые сделают это.Просто убедитесь, что nuller вызывается где-то в блоке finally, чтобы он всегда вызывался.

...