Отличный программист Java должен понять, как работает GC, как оптимизировать производительность GC и как иметь ограниченное взаимодействие с GC, потому что некоторые приложения имеют высокопроизводительные требования, такие как встроенные системы, системы в реальном времени и т. Д., Которые могут быть только Полное улучшение. В этой статье сначала кратко вводит принцип работы GC, а затем проводит подробные дискуссии по нескольким ключевым вопросам GC и, наконец, выдвигает некоторые предложения по программированию Java для улучшения эффективности программ Java с точки зрения GC.
Основные принципы GC
Управление памятью Java на самом деле является управлением объектами, включая распределение и выпуск объектов.
Для программистов новое ключевое слово используется для распределения объектов; .GC будет отвечать за восстановление пространства памяти всех /"недоступных /" ".
Для GC, когда программист создает объект, GC начинает отслеживать адрес, размер и использование объекта. Как правило, GC использует направленные графики для записи и управления всеми объектами в куче (Heap) (для получения подробной информации см. 1). Таким образом, какие объекты являются /«достижимыми /» и какие объекты являются /«недоступны /». Однако, чтобы обеспечить реализацию GC на различных платформах, спецификации Java не устанавливают много поведения GC. Например, нет четких правил по важным вопросам, таким как тип алгоритма переработки для использования и когда выполнять переработку. Следовательно, различные реализователи JVM часто имеют разные алгоритмы реализации. Это также привносит неопределенность в разработку программистов Java. В этой статье рассматриваются несколько вопросов, связанных с работой GC, и стремится уменьшить негативное влияние этой неопределенности на программы Java.
ИНКРЕМЕНТАЛЬНЫЙ GC (инкрементальный GC)
GC обычно реализуется в JVM одним или группой процессов. Поэтому, когда GC работает в течение долгого времени, пользователь может почувствовать паузу программы Java. Все еще много объектов, которые должны быть переработаны, которые не были переработаны. Следовательно, при разработке GC необходимо взвесить время паузы и скорость восстановления. Хорошая реализация GC позволяет пользователям определять настройки, которые им нужны. Другие онлайн-игры в реальном времени не могут допустить долгосрочные перерывы в программе. Инкрементальный GC-это разделить долгосрочное прерывание на многие небольшие прерывания с помощью определенного алгоритма утилизации, тем самым уменьшая влияние GC на пользовательские программы. Хотя инкрементальный GC может быть не таким эффективным, как обычный GC в общей производительности, он может сократить максимальное время паузы программы.
Hotspot JVM, предоставленная Sun JDK, может поддерживать Incremental GC. Реализация Hotspot JVM Incremental GC заключается в использовании алгоритма поезда GC. Основная идея состоит в том, чтобы сгруппировать все объекты в кучу (иерархически) в соответствии с созданием и использованием, поместить объекты с частым и очень актуальным использованием в очереди и продолжает группироваться, поскольку программа выполняет корректировку. Когда GC работает, он всегда перерабатывает самые старые (редко посещаемые недавно) сначала), и если вся группа является утилизируемым объектами, GC перерабатывает всю группу. Таким образом, каждый запуск GC будет переработать только определенную долю недоступных объектов, чтобы обеспечить плавную работу программы.
Подробное объяснение функции завершения
infintize - это метод, расположенный в классе объекта. Поскольку функция «Закончить» не автоматически реализует цепные вызовы, мы должны реализовать их вручную, поэтому последним утверждением функции «Окончания» обычно является супер .finalize (). Таким образом, мы можем реализовать призыв к внедрению «Закончить» снизу вверх, то есть сначала выпустить наши собственные ресурсы, а затем выпустить ресурсы родительского класса.
Согласно спецификации языка Java, JVM гарантирует, что этот объект недоступен, прежде чем вызовать функцию завершения, но JVM не гарантирует, что эта функция будет вызвана. Кроме того, спецификация также гарантирует, что функция завершения выполняется не более одного раза.
Многие новички Java будут думать, что этот метод похож на деструктор в C ++, и в этой функции выпускает множество объектов и ресурсов. На самом деле, это не хороший способ. Есть три причины. Во -вторых, после завершения выполнения завершения завершения, объект может стать достижимым, и GC необходимо снова проверить, достижим ли объект. Следовательно, использование infintize снизит производительность GC. В -третьих, поскольку время, когда GC Callize завершит, неясно, также неясно выпускать ресурсы таким образом.
Как правило, Finalize используется для выпуска некоторых ресурсов, которые нелегко контролировать и очень важны, например, некоторые операции ввода -вывода и соединения данных. Выпуск этих ресурсов очень критичен для всего приложения. В этом случае программисты должны в основном управлять этими ресурсами посредством самой программы (включая выпуск) и дополнять метод выпуска ресурсов с помощью функции завершения в качестве дополнения, чтобы сформировать механизм управления двойным страхованием, а не полагаться исключительно на завершение для выпуска ресурсов.
Вот пример, чтобы проиллюстрировать, что после того, как функция завершается, это все еще может быть достижимо.
класс myobject {test main; /Восстановить этот объект так, чтобы этот объект мог достичь System.out.println (/«Это завершено. ] args) {test test = new Test (); .ref! = null) System.out.println (/"Мой объект все еще жив/");
Результаты работы:
Это завершит
MyObject все еще жив
В этом примере следует отметить, что, хотя объект MyObject становится достижимым объектом в завершении, в следующий раз, когда вы перерабатываете, Finalize больше не будет вызвана, потому что функция завершения вызывает только один раз.
Как программа взаимодействует с GC
Java2 улучшает функции управления памятью и добавляет пакет java.lang.ref, который определяет три эталонных класса. Эти три эталонные классы - это Softreference, SleaseReference и PhantomReference. Справочные сильные стороны этих эталонных классов находятся между достижимыми и недоступными объектами.
Также очень легко создать справочный объект Установите нормальную ссылку на NULL. В то же время мы называем этот объект мягким эталонным объектом.
Основная особенность мягкой ссылки заключается в том, что он имеет сильные функции цитирования. Этот тип памяти перерабатывается только тогда, когда недостаточно памяти, поэтому, когда есть достаточная память, они обычно не переработаны. Кроме того, эти эталонные объекты также могут быть установлены на NULL до того, как Java выбрасывает исключение Outfmemory Ниже приведено следующее использование псевдокода для этого типа эталонного типа;
// Применение изображение изображения изображения = новое изображение (); // Создать объект изображения ... // Использование Image ... // После использования изображения установите его на тип мягкого эталона и выпустить сильную ссылку; = новый Softrefere (Image); Это должно быть перезагружено;
Самая большая разница между слабыми эталонными объектами и мягкими эталонными объектами заключается в том, что при переработке GC он должен использовать алгоритм, чтобы проверить, переработаны ли мягкие эталонные объекты, в то время как GC всегда перерабатывает слабые эталонные объекты. Слабые эталонные объекты проще и быстрее перерабатывать GC. Хотя GC должен перерабатывать слабые объекты при запуске, группа слабых объектов со сложными отношениями часто требует нескольких прогонов GC для завершения. Слабые эталонные объекты часто используются в структурах карт для обозначения объектов с большими объемами данных.
Призрачные ссылки менее полезны и в основном используются для оказания помощи в использовании функций завершения. Призрачные объекты относятся к некоторым объектам, которые завершили функцию завершения и являются недоступными объектами, но они не были переработаны GC. Этот вид объекта может помочь завершить некоторые более поздние работы по переработке.
Некоторые предложения по кодированию Java
Согласно принципу работы GC, мы можем использовать некоторые навыки и методы, чтобы GC работал более эффективно и в большей степени в соответствии с требованиями приложения. Вот несколько предложений по программированию.
1. Самое основное предложение - как можно скорее выпустить ссылки на бесполезные объекты. Когда большинство программистов используют временные переменные, они автоматически устанавливают эталонную переменную на NULL после выхода из активного домена (область применения). Графики и т. Д. Имеют сложную связь между этими объектами. Для таких объектов GC перерабатывает их, как правило, менее эффективно. Если программа разрешает это, назначьте неиспользованный эталонный объект как можно скорее. [Страница]
2. Попробуйте использовать функцию завершения как можно меньше. Функция завершения - это возможность для Java предоставить программистам возможность выпустить объекты или ресурсы. Тем не менее, это увеличит рабочую нагрузку GC, поэтому постарайтесь использовать как можно меньше для переработки ресурсов.
3. Если вам нужно использовать часто используемые изображения, вы можете использовать тип мягкого приложения. Он может сохранить изображение в памяти как можно больше, чтобы программа могла вызовать, не вызывая переоборудования.
4. Обратите внимание на типы данных сбора, включая структуры данных, такие как массивы, деревья, графики и связанные списки. Кроме того, обратите внимание на некоторые глобальные переменные, а также на некоторые статические переменные. Эти переменные, как правило, легко вызывают висящие ссылки, вызывая отходы памяти.
5. Когда у программы есть определенное время ожидания, программист может вручную выполнять System.gc (), чтобы уведомлять GC для запуска, но спецификация языка Java не гарантирует, что GC выполнит. Использование инкрементного GC может сократить время паузы программ Java.