2013-11-07 4 views
2

Этот класс инициализируется методом init() сервлета. objA используется только для чтения, необходимо периодически вызывать метод, чтобы заменить его новым экземпляром A.Замена объектов Java во время выполнения

Проблема: После периодических обновлений появляется утечка памяти. (Я предполагаю, что есть некоторые повисшие ссылки несколько копий A существующего)

public Class A { 

private static volatile A objA; 

public static A getA(){ 

    if(objA == null){ 

     synchronized (A.class){ 

      if(objA == null){ 
       objA = new A(); //takes a long time to initialise and memory heavy 
       return objA; 
      } 

     } 
    } 
    return objA; 
} 

    public static void refreshA (A newObjA){ 
     // best way to do this ? 
     /* 
     objA = newObjA; 
     */ 
    } 
} 

Вид Hacky:

Я мог бы использовать ConcurrentHashMap<String,A> -> get("OBJ-A"), replace("OBJ-A", newObjA)

это будет использовать ReentrantReadWriteLock но Я еще не пробовал.

Так что было бы лучшим способом реализовать refreshA()? Помня о том, что GC должен удалить старую ссылку.

+0

Если старый объект не собирается, это связано с тем, что он связан откуда-то еще. (Но, конечно, многие подозреваемые «утечки памяти» объясняются только тем, как работает GC - куча растет до тех пор, пока не будет достигнут предел, а затем собирается.) –

+0

Просто синхронизация на A.class и установка ссылки достаточно здесь , @HotLicks прав, ваша проблема не в этом классе. – Kayaman

+0

Здесь не обнаружено утечки. Подумайте о большей картине. Как другие классы используют результат getA()? Кроме того, если A - тяжелый объект для создания, почему бы не обновить его, заменив его, а не копируя состояния из других объектов/источников в objA? –

ответ

1

Прежде всего, двойной контроль блокировки не рекомендуется , см. En.wikipedia.org/wiki/Double-checked_locking.

Что касается заменяемого поля, вы можете использовать AtomicReference.

И что касается утечки памяти, рассмотрите вопрос о выдаче прокси-сервера фактическому объекту. Таким образом, вы можете поменять экземпляр резервного копирования и убедиться, что никто не ссылается на старый объект поддержки.

+0

в конечном итоге использует перечисление singleton :) AtomicReference звучит хорошо ... damn java fraking огромный !!! – jknair

0

Похоже, вы выяснили, как (повторить) реализовать синглтон и операцию обновления.

Я хочу сосредоточиться на некоторых других вещах в вашем Вопросе.

  1. (Pure) Java не может иметь свисающие ссылки. Значения в любой ссылке любого живого объекта в Java будут либо null, либо действительной ссылкой на существующий объект. Это относится даже к недостижимым объектам.

  2. Висячие ссылки (то есть указатели, которые больше не указывают на действительный объект) не вызывают утечки памяти. Скорее они являются признаком кучи коррупции. В Java, если JVM (включая GC) попытался использовать оборванную ссылку, результат, скорее всего, будет тяжелым сбоем.

  3. Если не совсем ясно, что вы думаете о связи между утечкой памяти и периодическим обновлением. Однако:

    • Периодическое обновление почти наверняка не причиной этой утечки памяти. Конечно, это не так, по свидетельству кода, который вы нам показали.

    • Периодическое обновление не гарантирует исцеления утечки памяти, если только статический ток A не содержит единственную долгосрочную ссылку на экземпляр A, который протекает. В самом деле, если вы «обновляете» A синглтон таким образом, существует четкая возможность, что вы будете вызывать утечку.Например, если какой-либо другой код вызывает метод getA() и кэширует результат где-то, когда вызывается A.refreshA(), вы получите два экземпляра TWO A, и первый из них действительно просочился.

Наконец ваша операция обновления нарушение неявные одноэлементные семантики A. Это может вызвать всевозможные проблемы , включая проблемы с потоками.


Если вы подозреваете, что ваш A класс является причиной утечки памяти, то лучший подход к устранению проблемы заключается в следующем:

  • фигура, какая часть A-х состояние является опасной частью утечки и

  • добавить синхронизированный instance метод A к ясно это состояние.

Обратите внимание, что не все утечки вредны. Объект, который существует для времени жизни приложения (например, static), может представлять собой утечку (к детектору утечки), но не вызовет никаких проблем.

+0

Плохой выбор слов относительно болтающихся ссылок, что я имел в виду, это вторая пуля на третьей точке, два или более экземпляра 'A'. Но я убедился, что такой шаг кэширования нигде не встречается. Таким образом, существует один метод, который выполняет 'getA()' и создает локальный объект 'A', из которого считываются данные, ответ выплевывается и возвращает void. В этом процессе, если произойдет переключение, что произойдет со старой ссылкой, это будет для GC? – jknair

Смежные вопросы