Подтвердить что ты не робот

Что такое беспроигрышный ресурс?

Я читаю " Эффективная Java".

В обсуждении о завершении он говорит

Деструкторы С++ также используются для восстановления других ресурсов nonememory. В Java для этой цели обычно используется блок finally try.

Каковы ресурсы без памяти?

Является ли соединение с базой данных ресурсом nonmemory? Не занимает ли объект для соединения с базой данных какая-то память?

4b9b3361

Ответ 1

Соединения с базами данных, сетевые подключения, файловые дескрипторы, мьютексы и т.д. Что-то, что должно быть выпущено (а не только сбор мусора), когда вы закончите с ним.

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

Ответ 2

Является ли соединение с базой данных ресурсом без памяти?

Да, это один из наиболее распространенных примеров. Другие - это дескрипторы файлов, собственные GUI-объекты (например, Swing или AWT-окна) и сокеты.

Не поддерживает ли объект для подключения к базе данных некоторую память?

Да, но дело в том, что часть памяти, которая не является частью памяти, также должна быть выпущена, и, как правило, намного скуднее, чем сравнительно небольшой объем памяти, используемой объектом. Как правило, такие объекты имеют метод finalize(), который освобождает ресурс без памяти, но проблема в том, что эти финализаторы будут выполняться только тогда, когда объекты собираются в мусор.

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

Это может даже вызвать проблемы только с одним объектом: например, если вы хотите переместить файл между файловыми системами, открыв его, открыв целевой файл, скопировав данные и затем удалив исходный файл, удаление завершится неудачно, если файл все еще открыт - и это почти наверняка будет, если вы только установите ссылку на входной поток на нуль и не вызываете close() явно, потому что очень маловероятно, что сборщик мусора будет работать точно так же точка между объектом, имеющим право на сбор мусора, и вызов delete()

Ответ 4

Вопрос лучше ответить наоборот, на мой взгляд, "почему мне не нужно освобождать память вручную".

Возникает вопрос: "Почему мне нужно освобождать какие-либо ресурсы?"

По сути, ваша работающая программа использует множество форм ресурсов для выполнения и выполнения работы (циклы процессора, места памяти, доступ к диску и т.д.). Почти все из них страдают от "дефицита", т.е. Существует фиксированный пул любого такого ресурса, если все ресурсы распределены, то ОС не может удовлетворить запросы и, как правило, ваша программа не может продолжать и умирает очень несносно - возможно, делая всю систему неустойчивой. Единственное, что приходит в голову, что это не так сложно, это циклы CPU, вы можете выпускать столько из них, сколько хотите, вы ограничены только тем, с какой скоростью вы можете их выдать, они не потребляются в одном и том же что память или файлы обрабатываются.

Таким образом, любой ресурс, который вы используете (память, дескрипторы файлов, подключения к базе данных, сетевые сокеты и т.д.), исходит из фиксированного количества такого ресурса (избегая слова "пул" ) и как ваша программа (и, -на других программах, не говоря уже о самой ОС) выделяет эти ресурсы, количество доступных уменьшается.

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

Pre-90s, управление ресурсами (по крайней мере, в основной разработке) было проблемой, с которой каждый программист должен был иметь дело явно. Некоторые управления распределением ресурсов не слишком сложны, главным образом потому, что выделение уже абстрагировано (например, файловые дескрипторы или сетевые сокеты), и можно получить ресурс, использовать его и явно освободить, когда он больше не нужен.

Однако управление памятью очень сложно, особенно, поскольку распределение памяти не может (в нетривиальных ситуациях) рассчитываться во время разработки, тогда как, например, связь с базой данных может быть осуществлена ​​таким образом. (Нет способа узнать, сколько памяти вы будете использовать, очень сложно/невозможно узнать, когда выделение памяти больше не используется). Кроме того, выделение памяти имеет тенденцию некоторое время зависать, когда большинство других распределений ресурсов ограничено узкой областью, часто в пределах одного блока try или метода, как правило, обычно класса. Поэтому поставщики разработали методы абстрагирования выделения памяти и приведения их в единую систему управления, управляемую исполняемой средой, а не программой.

В этом разница между управляемыми средами (например, Java,.NET) и неуправляемыми (например, C, С++ выполняется непосредственно через ОС). В C/С++ распределение памяти выполняется явно (с помощью malloc()/new и связанного с ним перераспределения), что приводит к разным проблемам - сколько мне нужно? Как рассчитать, когда мне нужно больше/меньше? Как освободить память? Как я могу убедиться, что я не использую память, которая уже была выпущена? Как определить и управлять ситуациями, когда запрос на распределение памяти не удается? Как избежать записи над памятью (возможно, даже моей собственной памяти)? Все это чрезвычайно сложно и приводит к утечкам памяти, дампам ядра и всевозможным полуслучайным, невоспроизводимым ошибкам.

Итак, Java реализует автоматическое управление памятью. Программист просто выделяет новый объект и не заинтересован и не должен быть в терминах того, что или где выделяется память (это также не так много способов указателей в управляемых средах):

object thing = new Object();

и что все это нужно сделать. JVM будет отслеживать, какая память доступна, когда ей нужно выделять ее, когда она может быть выпущена (поскольку она больше не используется), позволяя максимально гибко справляться с ситуациями с памятью (и ограничивать любые проблемы с выполнение потока /JVM и не сведение всей ОС).

Автоматическое управление памятью является стандартом с большинством программ в настоящее время, поскольку управление памятью на сегодняшний день является самым сложным ресурсом для управления (главным образом, поскольку другие уже частично отвлечены, пулы подключений к базе данных, абстракции сокетов и т.д.).

Итак, чтобы ответить на вопрос, да, вам нужно управлять всеми ресурсами, но в Java вам не нужно (и не может) явно управлять памятью самостоятельно (хотя в некоторых ситуациях это стоит рассмотреть, например, кэш). Это оставляет все другие ресурсы, которые вам необходимы для явного управления (и это ресурсы без памяти, т.е. Все, кроме создания/уничтожения объекта).

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

например.

public void server()
{
  try
  {
    ServerSocket serverSocket = new ServerSocket(25);
  }
  catch (Exception exception)
  {
     // Something went wrong.
  }
  finally
  {
    // Clear up and deallocate the unmanaged resource serverSocket here.
    // The close method will internally ensure that the network socket is actually flushed, closed and network resources released.
    serverSocket.close();
    // The memory used by serverSocket will be automatically released by the JVM runtime at this point, as the serverSocket has gone out-of-scope- it is never used again, so can safely be deallocated.
  }
}