powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / Утечка памяти. Где?
7 сообщений из 7, страница 1 из 1
Утечка памяти. Где?
    #37879676
GorloPavel
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Здравствуйте. Где-то тут утекает память... Помогите разобраться где. Заранее огромное спасибо!

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
public synchronized void autorizeServer(Session session,String[] autorizeInfo)
	{
		PreparedStatement command=null;
		ResultSet result=null;
		
		try {

			command = hub_DB_Connection.prepareStatement("SELECT * FROM users WHERE account_name=? AND account_pass=?");
			command.setString(1,autorizeInfo[0]);
			command.setString(2,autorizeInfo[1]);
			
			result = command.executeQuery();
			
            //Если учетная запись существует, то..
		    if (result.next()) {
				
		    	session.account_id = result.getInt(1);
                
		    	result.close();
		    	
			result = command.executeQuery(String.format("SELECT * FROM servers WHERE ACCOUNT_ID=%s",session.account_id));
				
				//Если запись уже есть в таблице, значит сервер с такими данными авторизирован
				if(result.next())
				{
					session.disconnect();
				}
				else
				{
					try 
					{   
						//Извлекаем имя и пароль
						session.account_name = autorizeInfo[0].toLowerCase();
						session.account_pass = autorizeInfo[1].toLowerCase();
                        
						//Если есть еще информация(порт, версия и т.д), то извлекаем...
						if (autorizeInfo.length > 2) {
							session.direct_port = Integer.parseInt(autorizeInfo[2]);
						}
						
						if(autorizeInfo.length>3)
						{
							session.version=autorizeInfo[3];
						}
						
						if(autorizeInfo.length>4)
						{
							session.local_ip_address=autorizeInfo[4];
						}
						
						if(autorizeInfo.length>5)
						{
							session.mac_address=autorizeInfo[5];
						}
						
						
						//Пытаемся создать занести запись в таблицу активных подключений...
						command.executeUpdate(String.format("INSERT INTO servers(account_id,ip_address,version,direct_port,local_ip_address,mac_address,country,city) VALUES(%s,'%s','%s',%s,'%s','%s','%s','%s')",
										                     session.account_id, session.ip_address,session.version,session.direct_port,session.local_ip_address,session.mac_address,session.country,session.city));
						
						command.executeUpdate(String.format("INSERT INTO connections_log(account_id,ip_address,connect_date_time,type,mac_address) VALUES(%s,'%s',NOW(),'SERVER','%s')",
								                             session.account_id,session.ip_address,session.mac_address));
						
						if(command.executeQuery("SELECT LAST_INSERT_ID()").next())
						{
							session.log_id=command.getResultSet().getInt(1);
							command.getResultSet().close();
						}
						
						hub_DB_Connection.commit();
						
						session.sessionType = Session.SessionType.Server;
					
						//Если все хорошо, то отправлем пользователю сообщение о том что он в сети!
						session.sendData("Online".getBytes());

					} 
					catch (Exception e) 
					{
						 //Делаем ROLLBACK
						 hub_DB_Connection.rollback();
						 //Отключаем клиента
						 session.disconnect();
					}
				}

			} 
		    else {
		    	//Пользователь с такими данными не зарегистрирован 
				session.sendData(("Errors"+ "Invalid username or password").getBytes());
				session.disconnect();
			}
		}
		catch (Exception e) {
			Date date = new Date();
    		        System.out.println(String.format("[%s]", dateFormat.format(date)));
			System.out.println("---ERROR---");
			e.printStackTrace();
			System.out.println("---ERROR---");
			session.disconnect();
		}
		finally
		{
			try
			{
				if(command!=null){command.close();}
				if(result!=null){result.close();}
			}
			catch(SQLException e)
			{
				Date date = new Date();
	    		        System.out.println(String.format("[%s]", dateFormat.format(date)));
				System.out.println("---ERROR---");
				e.printStackTrace();
				System.out.println("---ERROR---");
			}
		}
	}



Через некоторое время при вызове этой функции программа валится в:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
java.lang.OutOfMemoryError: Java heap spacecom.mysql.jdbc.SQLError.createSQLException(SQLError.java:1073)
com.mysql.jdbc.SQLError.createSQLException(SQLError.java:987)
com.mysql.jdbc.SQLError.createSQLException(SQLError.java:982)
com.mysql.jdbc.SQLError.createSQLException(SQLError.java:927)
com.mysql.jdbc.Util.handleNewInstance(Util.java:435)
com.mysql.jdbc.PreparedStatement.getInstance(PreparedStatement.java:872)
com.mysql.jdbc.ConnectionImpl.clientPrepareStatement(ConnectionImpl.java:1490)
com.mysql.jdbc.ConnectionImpl.prepareStatement(ConnectionImpl.java:4253)
com.mysql.jdbc.ConnectionImpl.prepareStatement(ConnectionImpl.java:4152)
GPPHub.autorizeServer(GPPHub.java:434)
Session.ReturnPacket(Session.java:306)
PacketParser.Analyze(PacketParser.java:148)
Session$DataReader.run(Session.java:152)
java.lang.Thread.run(Thread.java:662)

...
Рейтинг: 0 / 0
Утечка памяти. Где?
    #37879701
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну, например, если command.close() выкинет исключение, то ResultSet зыкрыт не будет. А вообще гадать по коду это неблагодарное занятие. Запускаем jvisualvm делаем дамп кучи и анализируем лишние объекты.
...
Рейтинг: 0 / 0
Утечка памяти. Где?
    #37879703
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну, и код - каша. Не до конца отформатирован. Непонятные имена переменных. Переменная result переиспользуется для двух resultset-ов. Понять такой код очень сложно. Какой был смысл экономить на переменных? Заведите отдельные переменные. Метод сам по себе большой и делает много всего и сразу. Почему PreparedStatement это command? Ничего ведь общего. Перенос строки вы очень любите, а вот пробелы недолюбливаете. Используйте автоматическое форматирование в IDE хотябы.
То что вы не используете preparedstatement, как минимум снижает производительность да. Объяснили ведь в другой теме что String.format к подстановке переменных в SQL лучше не применять.
Ну и ещё несколько замечаний по коду, но уже лень строчить.
...
Рейтинг: 0 / 0
Утечка памяти. Где?
    #37882273
Кореец
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
BlazkowiczТо что вы не используете preparedstatement, как минимум снижает производительность да.

В каком смысле не использует?
там же есть объявление.

PreparedStatement command=null;
...
Рейтинг: 0 / 0
Утечка памяти. Где?
    #37882291
Фотография Blazkowicz
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
КореецВ каком смысле не использует?
там же есть объявление.
PreparedStatement command=null;

Объявить переменную, ещё не значит использовать объект. Там 4 запроса с параметрами. И только первый реализован через PreparedStatement. Остальные 3 через подстановку строки.


...

Кстати, только заметил, ведь LAST_INSERT_ID() не нужен. ReturnGeneratedKeys все адекватные драйвера уже поддерживают.
...
Рейтинг: 0 / 0
Утечка памяти. Где?
    #37882415
chpasha
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
не совсем по теме но: зачем два select в начале метода? что left join не модно? зато на спичках экономим.
...
Рейтинг: 0 / 0
Утечка памяти. Где?
    #37882711
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
chpashaне совсем по теме но: зачем два select в начале метода? что left join не модно? зато на спичках экономим.
Это спорно. Мы не знаем архитектуру БД и возможно ступенчатая проверка несёт свои плюсы.
По крайней мере я находил выгоды в раздельных курсорах по 1 и 2 таблице (есть даже забавный
пример с min/max где план дорожает).

Другое дело что один и тот-же резалт-сет используется в разных контекстах. Это плохо. Сложно
отслеживать инициализацию, и вообще дурной стиль.
...
Рейтинг: 0 / 0
7 сообщений из 7, страница 1 из 1
Форумы / Java [игнор отключен] [закрыт для гостей] / Утечка памяти. Где?
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]