В прошлом, когда я узнал о сильных, слабых и слабых цитатах, я просто посмотрел на блоги, наблюдая за цветами, и не писал код, чтобы попрактиковаться и доказать это сам. В результате, после чтения его каждый раз, я забыл Это вскоре. Позже я решил набрать его сам. Стук в код, чтобы сделать впечатление более глубоко, древние сказали: на бумаге вы будете чувствовать себя мелкой, и вы должны сделать это, если вы это знаете, Отказ
Четыре вида ссылок в Java
В Java существует четыре типа ссылок: сильные ссылки, мягкие ссылки, слабые ссылки и виртуальные ссылки.
Почему Java разработала эти четыре ссылки
Распределение памяти Java и сборка мусора, программистам не нужно нести ответственность, брать на себя ответственность за все великие JVM, можно ли переработать объект, в основном, чтобы увидеть, есть ли ссылки на этот объект, скажем, профессиональная точка, называемая анализом достижимости.
Существуют две основные цели Java для разработки этих четырех типов ссылок:
- Вы можете сделать программистом, чтобы определить жизненный цикл объекта через код;
- Хорошо подходит для сбора мусора.
сильная цитата
Сильная ссылка является наиболее распространенным видом ссылки, 99,9999% кода, который мы пишем, является сильной ссылкой:
Object o = new Object();
Это сильная отсылка, она везде в коде, самая сердечная. Пока у объекта есть сильная ссылка, связанная с ним, объект никогда не будет восстановлен, даже если памяти недостаточно, JVM скорее выбросит OOM, чем вернет его.
Так когда же его можно будет переработать? Когда связь между строгой ссылкой и объектом нарушена, ее можно использовать повторно.
Мы можем вручную разорвать ассоциацию, и метод очень прост:
o = null;
Мы можем вручную вызвать GC, чтобы посмотреть, не прервана ли связь между сильной ссылкой и объектом, и ресурс будет переработан.Чтобы более удобно и наглядно наблюдать ситуацию с переработкой, нам нужно написать новый класс, а затем recycle Напишите метод finalize, давайте проведем такой эксперимент:
public class Student {
@Override
protected void finalize() throws Throwable {
System.out.println("Student 被回收了");
}
}
public static void main(String[] args) {
Student student = new Student();
student = null;
System.gc();
}
результат операции:
Student 被回收了
Отчетливо видно, что ресурсы были переработаны.
Конечно, в реальной разработке никогда не переписывайте метод finalize.
В реальной разработке очень вероятно, что некоторым объектам вручную присваивается значение NULL, чтобы «преднамеренно напомнить» JVM, что этот ресурс может быть удален сборщиком мусора.
Мягкие ссылки
Давайте сначала посмотрим, как создать мягкую ссылку:
SoftReference<Student>studentSoftReference=new SoftReference<Student>(new Student());
Мягкая ссылка заключается в том, чтобы обернуть объект с помощью SoftReference.Когда нам нужно получить обернутый объект из объекта мягкой ссылки, просто получите его:
SoftReference<Student>studentSoftReference=new SoftReference<Student>(new Student());
Student student = studentSoftReference.get();
System.out.println(student);
Каковы характеристики мягких ссылок: При нехватке памяти будет запущен GC JVM.Если памяти после GC по-прежнему недостаточно, то объект, обернутый мягкой ссылкой, будет уничтожен, то есть JVM будет перерабатывать объект только тогда, когда память недостаточный.
Тем не менее, вы должны экспериментировать, чтобы углубить свое впечатление:
SoftReference<byte[]> softReference = new SoftReference<byte[]>(new byte[1024*1024*10]);
System.out.println(softReference.get());
System.gc();
System.out.println(softReference.get());
byte[] bytes = new byte[1024 * 1024 * 10];
System.out.println(softReference.get());
Я определяю объект мягкой ссылки, который обертывает byte[], byte[] занимает 10M, а затем создает 10Mbyte[].
Для запуска программы нужно взять один параметр:
-Xmx20M
Он представляет максимальную память кучи - 20 м.
результат операции:
[B@11d7fff
[B@11d7fff
null
Хорошо видно, что после ручного завершения сборки мусора byte[], обернутый мягким эталонным объектом, все еще жив, но когда мы создаем 10M byte[], максимальной памяти кучи недостаточно, поэтому оберните мягкий эталонный объект Байт[] уничтожается, если не уничтожается, будет сгенерирован OOM.
Какая польза от мягких ссылок? Он больше подходит для использования в качестве кеша.Когда памяти достаточно, кеш можно получить нормально.Когда памяти не хватает, кеш будет убит в первую очередь, так что OOM не будет выброшен сразу.
слабая ссылка
Использование слабых ссылок аналогично мягким ссылкам, за исключением того, что ключевое слово становится WeakReference:
WeakReference<byte[]> weakReference = new WeakReference<byte[]>(new byte[1024*1024*10]);
System.out.println(weakReference.get());
Особенность слабых ссылок заключается в том, что они будут утилизированы до тех пор, пока выполняется сборка мусора, независимо от того, достаточно ли памяти:
WeakReference<byte[]> weakReference = new WeakReference<byte[]>(new byte[1]);
System.out.println(weakReference.get());
System.gc();
System.out.println(weakReference.get());
результат операции:
[B@11d7fff
null
Хорошо видно, что памяти по-прежнему достаточно, но GC срабатывает, а ресурсы по-прежнему перерабатываются. Слабые ссылки используются во многих местах, таких как ThreadLocal и WeakHashMap.
фантомная ссылка
Фантомные ссылки также известны как фантомные ссылки Давайте посмотрим на их использование:
ReferenceQueue queue = new ReferenceQueue();
PhantomReference<byte[]> reference = new PhantomReference<byte[]>(new byte[1], queue);
System.out.println(reference.get());
Разница между использованием виртуальных ссылок и мягкими ссылками и слабыми ссылками, упомянутыми выше, довольно велика.Давайте запустим ее напрямую, независимо от того, что такое ReferenceQueue:
null
Он выводит null, давайте посмотрим на исходный код метода get:
public T get() {
return null;
}
Это несколько значений, и он возвращает значение null напрямую.
Это одна из характеристик фантомных ссылок: невозможно получить реальную ссылку на объект через фантомную ссылку.
Каково значение существования виртуальных ссылок? Это вернемся к нашему коду выше. Давайте скопируем код, чтобы вы не переворачивали его снова:
ReferenceQueue queue = new ReferenceQueue();
PhantomReference<byte[]> reference = new PhantomReference<byte[]>(new byte[1], queue);
System.out.println(reference.get());
Чтобы создать виртуальный эталонный объект, помимо передачи обернутого объекта, мы также передали ReferenceQueue, что видно из названия как очередь.
Вторая особенность виртуальных ссылок заключается в том, что виртуальные ссылки должны использоваться с ReferenceQueue.Когда GC будет готов переработать объект, если он обнаружит, что у него все еще есть виртуальная ссылка, он добавит виртуальную ссылку в связанную с ним ReferenceQueue перед переработка.
Давайте потренируемся с кодом:
ReferenceQueue queue = new ReferenceQueue();
List<byte[]> bytes = new ArrayList<>();
PhantomReference<Student> reference = new PhantomReference<Student>(new Student(),queue);
new Thread(() -> {
for (int i = 0; i < 100;i++ ) {
bytes.add(new byte[1024 * 1024]);
}
}).start();
new Thread(() -> {
while (true) {
Reference poll = queue.poll();
if (poll != null) {
System.out.println("虚引用被回收了:" + poll);
}
}
}).start();
Scanner scanner = new Scanner(System.in);
scanner.hasNext();
}
результат операции:
Student 被回收了
虚引用被回收了:java.lang.ref.PhantomReference@1ade6f1
Кратко проанализируем код: Первый поток подставляет данные в коллекцию, и по мере увеличения данных обязательно произойдет GC. Второй поток бесконечно зацикливается, берет данные из очереди и распечатывает их, если извлеченные данные не равны нулю.
Из результатов можно увидеть: когда произошло GC, виртуальная ссылка будет восстановлена и переработана в уведомление будет в реферизировании.
Какая польза от фантомных ссылок? В NIO виртуальные ссылки используются для управления памятью вне кучи.
Это все для этого блога.