2012-03-29 3 views
1

Это проблема утечки памяти приложения Android.Android Memory Leak new Thread()

Я еще не знал, что следующий код вызывает утечку памяти, так как я начал программу Android в течение 3 лет.

Thread t = new Thread(); 

t НЕ обнаруживается сборщиком мусора.

Вопрос: как я могу освободить локальную переменную t из памяти vm?

Я решил поэкспериментировать

Я сделал кнопку на моем приложении, которое является поведением следующего кода.

for(int i=0;i<1000;i++) 
{ 
    Thread t = new Thread(); 
} 

Ожидаемая локальная переменная t будет освобождена в определенный день.

И я выполнил его в режиме отладки и открыл перспективу DDMS для клипов.

Я выбираю мой поток приложения на моем устройстве Android (2.3.6) и щелкнул «обновление куча» кнопка

так что я могу проверить размер кучи и выделяюсь на реальное время.

Начато с общей площади кучи 5.445MB и выделено 2.779 МБ.

И я нажал кнопку, которая производит 1000 объектов потока.

Он был изменен на кучу размером 5.508MB и выделен 3.058 MB.

Как вы знаете, есть кнопка «Причина GC» в перспективе DDMS.

Я нажал на эту кнопку. Но выделенная память все еще была 3.058MB.

Я снова нажал на свою кнопку, чтобы создать еще 1000 объектов потока.

И я нажал безнадежную кнопку «Gause GC».

В конце концов размер кучи ушел около 20 МБ и из-за исключения из памяти.

Как я могу освободить объект экземпляра Thread?

+0

В большинстве случаев лучше использовать Исполнителя вместо потока. Если вы используете что-то вроде cachedThreadPool, он будет обрабатывать активные потоки для вас. http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/Executor.html – Jave

ответ

1

После того как вы сделали, используя нить, вызовите interupt().

И я не знаю, если это необходимо, но было бы неплохо установить t=null, как было предложено Йоханнесом.

Но после того, как вы остановили поток, это зависит от сборщика мусора JVM, чтобы справиться с уничтожением самой нити.

+1

он не работает .... for (int i = 0, я <1000; я ++) \t \t \t \t { \t \t \t \t \t Thread т = новый Thread(); \t \t \t \t \t t.start(); \t \t \t \t \t t.interrupt(); \t \t \t \t \t t = null; \t \t \t \t} – muyoungko

+0

Ну. Это действительно не имеет значения. Не должно быть экземпляра, где вам нужно создать 1000 потоков. И создание одного потока не будет использовать столько памяти. И тот факт, что вы создаете так много потоков, может быть причиной проблемы. Если бы вы создали его, замените его и сделаете нулевым, то, скорее всего, он будет очищен из памяти. Если нет, то я не верю, что вы сможете это сделать. – Jakar

+0

Это фактически исправило это для моей ситуации, когда я создаю 7000 потоков за 20 минут, используя массив из 12 объектов Thread. @muyoungko Я замечаю, что ваш тест на цикл не имеет никакого запуска или чего-то еще - возможно, это часть проблемы ... вызов прерывания() слишком скоро после запуска()? В моей ситуации у меня есть AtomicBoolean (массив для нескольких потоков), который сообщает мне, что поток завершен, и затем я прерываю() в исходном объекте Thread перед созданием нового в том же слоте массива. Утечка памяти исчезла с этим решением. –

0

У меня нет устройства для Android, чтобы проверить его, но я думаю, что нить должна умереть, прежде чем она может быть собрана мусором в дополнение к тому, чтобы не ссылаться на какую-либо переменную.

Try начиная нити в цикле, как это:

for(int i=0;i<1000;i++) 
{ 
    Thread t = new Thread(); 
    t.start(); 
    t = null; 
} 
+1

он не работает – muyoungko