Сборка мусора в Java | Испытание августовского обновления

Java задняя часть
Сборка мусора в Java | Испытание августовского обновления

представлять

  • В C/C++ за создание и уничтожение объектов отвечает программист. Часто программисты игнорируют уничтожение бесполезных объектов. Из-за этого упущения в какой-то момент для создания нового объекта может не хватить доступной памяти, и вся программа аварийно завершится, что приведет кOutOfMemoryErrors.
  • Но в Java программистам не нужно заботиться обо всех объектах, которые больше не используются. Механизм сборки мусора автоматически уничтожает эти объекты.
  • Механизм сборки мусора — лучший пример потока демона, поскольку он всегда работает в фоновом режиме.
  • Основная цель механизма сборки мусора — уничтожитьнедоступный объектчтобы освободить память кучи.

Важные термины:

  1. Недоступный объект:Объект называется недостижимым, если он не содержит ссылок на него. Также обратите внимание, что объекты, принадлежащие карантинному острову, также недоступны.
Integer i = new Integer(4);
// 新的 Integer 对象可通过 'i' 中的引用访问
i = null;
// Integer 对象不再可用。

image.png

  1. Право на вывоз мусора:Если объект недоступен, говорят, что объект подходит для GC (сборки мусора). На картинке выше, впосле того, как я = ноль;Целочисленный объект 4 в области кучи подходит для сборки мусора.

Способы сделать объекты доступными для GC

  • Несмотря на то, что программисты не несут ответственности за уничтожение бесполезных объектов, настоятельно рекомендуется делать объекты недоступными (и, следовательно, подходящими для GC), если они больше не нужны.

  • Обычно существует четыре различных способа сделать объект подходящим для сборки мусора.

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

Все вышеперечисленные методы с примерами обсуждаются в отдельной статье: Как сделать объекты подходящими для сборки мусора

Как запросить JVM для запуска сборщика мусора

  • Как только мы делаем объект пригодным для сборки мусора, сборщик мусора не может уничтожить его немедленно. Всякий раз, когда JVM запускает программу сборщика мусора, уничтожаются только объекты. Но когда JVM запускает сборщик мусора, мы не можем предсказать.

  • Мы также можем запросить JVM для запуска сборщика мусора. Есть два способа сделать это:

  1. использоватьSystem.gc()метод: системный класс содержит статические методыgc()Используется для запроса JVM на запуск сборщика мусора.
  2. использоватьRuntime.getRuntime().gc()метод: класс среды выполнения позволяет приложению взаимодействовать с JVM, на котором запущено приложение. Итак, используя его метод gc(), мы можем попросить JVM запустить сборщик мусора.
// 演示请求 JVM 运行垃圾收集器的 Java 程序
public class Test
{
	public static void main(String[] args) throws InterruptedException
	{
		Test t1 = new Test();
		Test t2 = new Test();
		
		// 取消引用变量
		t1 = null;
		
		// 请求 JVM 来运行垃圾收集器
		System.gc();
		
		// 取消引用变量
		t2 = null;
		
		// 请求 JVM 来运行垃圾收集器
		Runtime.getRuntime().gc();
	
	}
	
	@Override
	// 在垃圾回收之前,在对象上调用一次 finalize 方法
	protected void finalize() throws Throwable
	{
		System.out.println("垃圾收集器调用");
		System.out.println("对象垃圾收集:" + this);
	}
}

вывод:

垃圾收集器调用
对象垃圾收集:haiyong.Test@7ad74083
垃圾收集器调用
对象垃圾收集:haiyong.Test@7410a1a9
  • Примечания:
    1. Нет никакой гарантии, что любой из двух вышеперечисленных методов обязательно запустит сборщик мусора.
    2. перечислитьSystem.gc()Эквивалент вызова:Runtime.getRuntime().gc()

завершенный

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

  • finalize()Методы существуют в классе Object со следующим прототипом.

protected void finalize() throws Throwable

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

Примечания:

  1. Вызывается сборщиком мусора вместо JVMfinalize()метод. Хотя сборщик мусора — это один из модулей JVM.
  2. класс объектаfinalize()Метод можно реализовать бесплатно, поэтому рекомендуется переопределитьfinalize()способ избавиться от системных ресурсов или выполнить другую очистку.
  3. Для любого заданного объектаfinalize()Метод никогда не вызывается более одного раза.
  4. еслиfinalize()метод выдает неперехваченное исключение, исключение игнорируется, и объект завершается.

Связанныйfinalize()Пример метода см. в выводе десятого набора сборки мусора Java-программы.

Давайте возьмем реальный пример, где мы используем концепцию сборщика мусора.

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

Вот фактические задания, которые вы получаете в компании:

просить:Напишите программу для создания класса Employee со следующими элементами данных.
1. Идентификатор для хранения уникального идентификатора, присвоенного каждому сотруднику.
2. Имя сотрудника.
3. Возраст сотрудников.

Кроме того, предусмотрены следующие методы:

  1. Конструктор с параметрами для инициализации имени и возраста. ID должен быть инициализирован в этом конструкторе.
  2. Метод show() для отображения ID, имени и возраста.
  3. Метод showNextId(), отображающий идентификатор следующего сотрудника.

Теперь новичок, который не понимает механизм сборки мусора, может написать такой код:

//计算在公司工作的员工人数的程序

class Employee
{
	private int ID;
	private String name;
	private int age;
	private static int nextId=1;
	//它是静态的,因为它在所有对象之间保持通用并由所有对象共享
	public Employee(String name,int age)
	{
		this.name = name;
		this.age = age;
		this.ID = nextId++;
	}
	public void show()
	{
		System.out.println
		("Id="+ID+"\nName="+name+"\nAge="+age);
	}
	public void showNextId()
	{
		System.out.println
		("Next employee id will be="+nextId);
	}
}
class UseEmployee
{
	public static void main(String []args)
	{
		Employee E=new Employee("GFG1",33);
		Employee F=new Employee("GFG2",45);
		Employee G=new Employee("GFG3",25);
		E.show();
		F.show();
		G.show();
		E.showNextId();
		F.showNextId();
		G.showNextId();
			
			{ //这是保留所有实习生的子块。
			Employee X=new Employee("GFG4",23);	
			Employee Y=new Employee("GFG5",21);
			X.show();
			Y.show();
			X.showNextId();
			Y.showNextId();
		}
		//这个大括号之后,X 和 Y 将被移除。因此现在它应该显示 nextId 为 4。
		E.showNextId();//这一行的输出应该是 4,但它会给出 6 作为输出。
	}
}

вывод:

image.png

Теперь получите правильный вывод:
Сборщик мусора (GC) теперь увидит два объекта холостого хода. Сейчас уменьшается следующим образом, сборщик мусора вызовов только, когда наши программисты переопределяют его в нашем классе. Завершить (). Как упоминалось ранее, мы должны запросить GC (сборщик мусора), для этого мы должны записать следующие три шага перед закрытием скобок подблокировки.

  1. Установите ссылку на null (т.е. X = Y = null;)
  2. вызов, System.gc();
  3. вызов, System.runFinalization();

Правильный код для подсчета сотрудников теперь (исключая стажеров)

// 计算不包括实习生的员工人数的正确代码
class Employee
{
	private int ID;
	private String name;
	private int age;
	private static int nextId=1;
	//它是静态的,因为它在所有对象之间保持通用并由所有对象共享
	public Employee(String name,int age)
	{
		this.name = name;
		this.age = age;
		this.ID = nextId++;
	}
	public void show()
	{
		System.out.println
		("Id="+ID+"\nName="+name+"\nAge="+age);
	}
	public void showNextId()
	{
		System.out.println
		("Next employee id will be="+nextId);
	}
	protected void finalize()
	{
		--nextId;
		//在这种情况下,gc 会为 2 个对象调用 finalize() 两次。
	}
}

// 它是 Employee 类的右括号
class UseEmployee
{
	public static void main(String []args)
	{
		Employee E=new Employee("GFG1",33);
		Employee F=new Employee("GFG2",45);
		Employee G=new Employee("GFG3",25);
		E.show();
		F.show();
		G.show();
		E.showNextId();
		F.showNextId();
		G.showNextId();
			
		{
			//这是保留所有实习生的子块。
			Employee X=new Employee("GFG4",23);	
			Employee Y=new Employee("GFG5",21);
			X.show();
			Y.show();
			X.showNextId();
			Y.showNextId();
			X = Y = null;
			System.gc();
			System.runFinalization();
		}
	E.showNextId();
	}
}

вывод:

image.png

😊 Что я хочу сказать в конце

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

Я уже довольно давно веду блог о технологиях, и в основном через самородки, вот одна из моих технических статей/руководств. Я люблю делиться технологиями и радостью через статьи. Пожалуйста, посетите мой блог:Хай ЙонгЧтобы получить больше информации. Надеюсь, вам это понравится! Вот краткое изложение всех моих оригинальных и исходных кодов работ:GitHub

Если вы действительно узнали что-то новое из этой статьи, ставьте лайк, добавляйте в закладки и делитесь с друзьями. 🤗Наконец, не забудьте поддержать ❤ или 📑