Intereting Posts
Передача двоичных данных через оболочку АБР (т.е. быстрая передача файлов с использованием tar) Что такое проблемы обновления и обновления приложений для Android? Стабилизация видео в реальном времени Как обращаться с ** Grid View ** при изменении конфигурации? Snackbar скрывает плавающее действие при нажатии на кнопку действия на нем Используйте панель инструментов для всех видов деятельности (Android) Текстура Android OpenGL из нелокального источника с использованием Rajawali3D? Как пройти Drawable с помощью Parcelable Вход в Google Android с Firebase – statusCode DEVELOPER_ERROR Разработка приложения для аварийных приложений Android AVD на Eclipse показывает «Пустой экран» без активности Как можно ограничить ориентацию ландшафтного экрана в андроиде? Запустить действие с использованием намерения и отключить нажатие кнопки «Назад» от запуска предыдущей операции Запустить приложение для Android, когда ссылка используется в SMS Форумы

Управление памятью HttpClient

У меня есть приложение с пулом потоков (ThreadPoolExecutor), которому передаются задачи, каждый из которых выполняет операцию HttpGet и считывает InputStream в байт [], чтобы что-то с этим делать.

После прочтения документов HttpClient я ушел с впечатлением, что лучший способ управлять соединениями HttpClient по нескольким потокам – это создать один ThreadSafeClientConnManager и поделиться им с приложением.

После реализации этого, я замечаю, что даже после завершения всех задач все еще сохраняется значительное количество памяти, используемой ThreadSafeClientConnManager.

Глядя на кучу кучи, эта память находится в виде массивов byte []. Эти ссылки не поддерживаются никакими ссылками, которые я создал. Их удерживают куски ThreadSafeClientConnManager и его пул. Я не уверен, связаны ли они с InputStreams или если они что-то еще.

Все задачи сами и их переменные успешно собираются с мусором.

Если я вызываю getConnectionManager (). Shutdown () в ThreadSafeClientConnManager, тогда вся память освобождается просто отлично. Однако я не хочу отключать соединение, потому что эти задачи HttpGet могут произойти в любое время. Я хотел бы оставить его открытым в течение срока службы приложений.

По мере запуска задач HttpGet сохраняемая память растет все больше и может в конечном итоге привести к ошибкам памяти. Когда задачи завершены, память не будет выпущена.

Как я могу обеспечить освобождение памяти после того, как закончившаяся задача была закончена?

Вот код, который я использую. Он собран вместе так же хорошо, как и код из документов HttpClient, другие вопросы здесь, в SO и в Интернете.

Создание HttpClient:

// Create and initialize HTTP parameters HttpParams params = new BasicHttpParams(); HttpConnectionParams.setConnectionTimeout(params, 40 * 1000); HttpConnectionParams.setSoTimeout(params, 40 * 1000); ConnManagerParams.setMaxTotalConnections(params, 100); HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); // Create and initialize scheme registry SchemeRegistry schemeRegistry = new SchemeRegistry(); schemeRegistry.register( new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); schemeRegistry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443)); // Create an HttpClient with the ThreadSafeClientConnManager. // This connection manager must be used if more than one thread will // be using the HttpClient. ClientConnectionManager cm = new ThreadSafeClientConnManager(params, schemeRegistry); mHttpClient = new DefaultHttpClient(cm, params); 

Затем Runnable, который выполняет HttpGet, в значительной степени основан на примере из примеров HttpClient для выпуска вручную . Вот пример того, как он выглядит:

 HttpClient httpclient = getTheSharedThreadSafeClientConnManager(); // Would return the mHttpClient from above try { HttpGet httpget = new HttpGet("http://www.apache.org/"); // Execute HTTP request System.out.println("executing request " + httpget.getURI()); HttpResponse response = httpclient.execute(httpget); System.out.println("----------------------------------------"); System.out.println(response.getStatusLine()); System.out.println("----------------------------------------"); // Get hold of the response entity HttpEntity entity = response.getEntity(); // If the response does not enclose an entity, there is no need // to bother about connection release if (entity != null) { InputStream instream = entity.getContent(); try { instream.read(); // do something useful with the response } catch (IOException ex) { // In case of an IOException the connection will be released // back to the connection manager automatically throw ex; } catch (RuntimeException ex) { // In case of an unexpected exception you may want to abort // the HTTP request in order to shut down the underlying // connection immediately. httpget.abort(); throw ex; } finally { // Closing the input stream will trigger connection release try { instream.close(); } catch (Exception ignore) {} } } } 

Нужно ли вам больше делать, чтобы выпустить ресурсы на одну задачу? Я видел в их примере ThreadSafeClientConnManager они использовали HttpContext, но я не могу найти документацию о том, как его использовать. Это необходимо? Если да, то как вы используете его с ThreadPoolExecutor?

Спасибо.

Solutions Collecting From Web of "Управление памятью HttpClient"

Вы когда-нибудь вызывали методы ClientConnectionManager releaseConnection (…) или closeExpiredConnections ()?

В блоке finally добавьте вызов HttpEntity.consumeContent ()

Известных проблем с управлением памятью в HttpClient 4.0 и 4.1 нет.

Какую версию HttpClient вы используете и что такое JRE?