Может иметь утечку памяти в веб-приложении Java - есть вопрос о сборке мусора и атрибутах сеанса - PullRequest
0 голосов
/ 26 января 2011

Я профилировал свое веб-приложение локально на моем компьютере с помощью VisualVM. Я почти уверен, что у меня небольшая утечка памяти. Сделав снимок приложения, я выбрал объект, у которого было наибольшее количество экземпляров объектов, и просмотрел Allocation Call Tree , чтобы посмотреть, смогу ли я найти, какой класс (мой) способствовал «потенциальной утечке» .

Я нашел три своих класса в дереве и взглянул на методы, которые были точно определены.

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

public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {

        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;


            try {           

            conn = ds.getConnection(); 
            stmt = conn.createStatement(); 

            HttpSession session = req.getSession();

            getExemptSessionAttributes(Customer_Number,rs,stmt,session);    

          }//try

            catch (Exception e) { }


            finally { 
                    if (rs != null) {
                      try { rs.close(); } catch (SQLException e) { ; }
                    }
                    if (stmt != null) {
                      try { stmt.close(); } catch (SQLException e) { ; }
                    }
                    if (conn != null) {
                      try { conn.close(); } catch (SQLException e) { ; }
                    }           

           }//finally        

       }//post            


    public void getExemptSessionAttributes(int Customer_Number, ResultSet rs, Statement stmt,                HttpSession session) {    
       try {
         rs = stmt.executeQuery("Select Name from exemptsessionattributes");
         String[] exemptAttributes = null;
         int count = 0;

         while(rs.next()) {
             count++;
          }
         rs.beforeFirst();

         exemptAttributes = new String[count];
         count = 0;

         while(rs.next()) {
            exemptAttributes[count] = rs.getString(1);
            count++;
            }
         session.setAttribute("ExemptSessionAttributes",exemptAttributes);

         //garbage collect
         exemptAttributes = null;
              }//try
              catch(Exception e) {}
    }//end

//....

Единственной модификацией, которую я сделал до сих пор, начиная с профилирования моего веб-приложения, было добавление установки для массива объекта exemptAttributes [] равным нулю.

Мой вопрос - Если массив String (или какой-либо объект) установлен в атрибуте сеанса, означает ли это, что ссылка на этот объект, если в коде не установлено значение NULL, все еще «ссылается» и не будет собирать мусор?

Ответы [ 3 ]

1 голос
/ 26 января 2011

Если массив String (или любой объект) установлен в атрибуте сеанса, означает ли это, что ссылка на этот объект, если в коде не установлено значение NULL, все еще «ссылается» и не будетбыть сборщиком мусора?

Не совсем.

Если вы установили объект в качестве атрибута сеанса, то этот объект будет оставаться доступным (а не сборщиком мусора) до тех пор, покакак объект Session достижим.Скорее всего, объект Session кэшируется в памяти инфраструктурой сервлета в течение длительного времени.

В этом случае присвоение null локальной переменной ничего не дает.Во-первых, местный житель в любом случае собирается выйти из области видимости, и это имеет тот же эффект с точки зрения GC.Во-вторых, вы только что скопировали ссылку на объект в структуру данных (объект Session), который имеет более длительное время жизни, чем локальная переменная ... так что объект все равно будет по-прежнему доступен.

Вкороче говоря, объект продолжает оставаться достижимым независимо от того, от того, присвоили ли вы null локальной переменной (или нет)

Возможные способы борьбы с этой "утечкой" включают:

  • не помещать ссылку на объект в атрибут сеанса,
  • установить атрибут сеанса на null или
  • настроить стратегию кэширования сеанса веб-контейнера так, чтобычто незанятые сеансы удаляются из кэша.
  • реализуют схему для аннулирования сеансов (например, выход пользователей из системы) после периода простоя.
1 голос
/ 26 января 2011

Область ссылки exemptAttributes (не фактический объект, на который ссылается ссылка) - это блок try в вашем методе.Таким образом, ответ на ваш вопрос выглядит так: « Нет ».

Может быть, утечка, потому что вы не уничтожаете сессии?Другими словами, если вы продолжите создавать новые сеансы и устанавливать объекты exemptAttributes в этих сеансах, ваше использование памяти будет расти, если вы не очищаете старые / неиспользованные сеансы.(вы можете установить тайм-аут сеанса в web.xml)

0 голосов
/ 26 января 2011

Чтобы ответить на ваш фактический вопрос, нет, обнуление этой ссылки почти ничего не значит.Переменная ограничена только этим блоком try {}.Он выходит из области видимости, как только вы покидаете попытку, и этот класс больше не удерживает ссылки.Очень мало «реальных» случаев, когда обнуление ссылки в методе делает что-то полезное для сборки мусора.Это будет продолжаться до тех пор, пока сессия не выпустит свою ссылку независимо от того.

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

...