日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java程序员的日常—— 垃圾回收中引用类型的作用

發布時間:2025/3/15 java 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java程序员的日常—— 垃圾回收中引用类型的作用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在Java里面,是不需要太過于關乎垃圾回收,但是這并不意味著開發者可以不了解垃圾回收的機制,況且在java中內存泄露也是家常便飯的事情。因此了解垃圾回收的相關知識就顯得很重要了。

引用,在垃圾回收中是一個很關鍵的概念,它關系到如何辨別這個對象是否被回收,什么時機回收。

引用的類型

在Java中引用的類型可以分為四個類型,依次是:

  • 強引用:在任何時間JVM都不會進行回收
  • 軟引用:在內存不夠的時候,JVM會進行回收
  • 弱引用:只要進行垃圾回收,就會觸發回收
  • 虛引用:不知道啥時候就被回收了,可以理解為沒引用一個樣

因此,按照JVM對他們回收的幾率從小到大依次為:

強引用<軟引用<弱引用<虛引用

也就是說JVM對強引用的回收能力最小,對虛引用的回收能力最大。

引用分類的作用

一般我們編寫的代碼都是強引用的,比如:

Person p = new Person(); Person p1 = p;

p和p1都指向了創建的Person對象,他們都是強引用的。如果想要回收這個對象,只有p1和p都指向null后,才可以。

那么,有一些場景下往往引用清除的不及時,就會造成內存泄露,一些對象無法回收;無法回收的對象如果積累很多,就會造成OUT OF MEMORY——OOM.

舉個例子,在很多的代碼里面都喜歡用Map作為內存緩存的容器,如果你寫出了這樣的代碼:

Map<String,Object> map = new HashMap<String,String>(); while(true){Object value = new XXX();map.add(key,value);value = null; }

雖然說,后面的value被設置成Null,但是map里面卻仍然保留了對象的引用,因此這個對象實際上是無法被回收的。

做個測試:

public class WeakTest {static final int MB = 1024 * 512;static String createLongString(int length) {StringBuilder sb = new StringBuilder(length);for (int i = 0; i < length; i++)sb.append('a');sb.append(System.nanoTime());return sb.toString();}public static void main(String[] args) {Map<Integer,String> substrings = new HashMap();//強引用的Mapfor(int i=0; i< 1000000; i++){String longStr = createLongString(MB);substrings.put(i,longStr); // longStr = null; // substrings.remove(i);System.out.println(i);}} }

如果注釋的兩句話不被打開,那么很快就會內存溢出。除非你兩邊都去解除應用,可想而知,程序員做這種工作實在是太痛苦了。

不要擔心,這個時候就可以應用到上面的不同類型的引用知識了

在Java里面,JDK為我們提供了一個弱引用的集合,WeakHashMap。它會在垃圾回收的時候嘗試回收集合里面的對象。當然根據垃圾回收的時機,也可以選擇軟引用的集合。

public static void main(String[] args) {Map<Integer,String> substrings = new WeakHashMap();//弱引用的Mapfor(int i=0; i< 1000000; i++){String longStr = createLongString(MB);substrings.put(i,longStr);System.out.println(i);}}

這樣就不擔心內存溢出了。

場景設想

比如,你的系統需要引用大量的資源相關的緩存,但是還沒有引入redis等緩存系統,那么就可以使用這種方式。

虛引用

虛引用的使用場景就比較雞肋了,我也想不出什么時候會使用它。但是它跟其他的引用都有一種場景,就是在垃圾回收的時候,把引用放在回收隊列里面,針對這個隊列可以做一些操作。這種方式比finalize()要文檔的多..

public class PhantomTest {public static boolean isRun = true;public static void main(String[] args) throws Exception {String abc = new String("abc");System.out.println(abc.getClass() + "@" + abc.hashCode());final ReferenceQueue referenceQueue = new ReferenceQueue<String>();new Thread() {public void run() {while (isRun) {Object o = referenceQueue.poll();if (o != null) {try {Field rereferent = Reference.class.getDeclaredField("referent");rereferent.setAccessible(true);Object result = rereferent.get(o);System.out.println("gc will collect:"+ result.getClass() + "@"+ result.hashCode());} catch (Exception e) {e.printStackTrace();}}}}}.start();PhantomReference<String> abcWeakRef = new PhantomReference<String>(abc,referenceQueue);abc = null;Thread.currentThread().sleep(3000);System.gc();Thread.currentThread().sleep(3000);isRun = false;}}

首先需要創建一個引用隊列:

final ReferenceQueue referenceQueue = new ReferenceQueue<String>();

創建虛引用,并關聯到引用隊列

PhantomReference<String> abcWeakRef = new PhantomReference<String>(abc,referenceQueue);

等引用被回收的時候,就會在Object o = referenceQueue.poll();取到對象引用了。

雖然一般不會有這種底層的使用場景,但是了解一點總歸是好的。

本文轉自博客園xingoo的博客,原文鏈接:Java程序員的日常—— 垃圾回收中引用類型的作用,如需轉載請自行聯系原博主。

總結

以上是生活随笔為你收集整理的Java程序员的日常—— 垃圾回收中引用类型的作用的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。