加入收藏 | 设为首页 | 会员中心 | 我要投稿 河北网 (https://www.hebeiwang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 建站 > 正文

Java 中的四种引用

发布时间:2019-10-24 19:00:11 所属栏目:建站 来源:健程之道
导读:之前我们提到过 GC,但当 Java 中引用的工具越来越多,会导致内存空间不敷,最终会发生错误 OutOfMemoryError,并让应用措施终止。那为什么 GC 在此时不能多网络一些工具呢?这就和本日说的引用范例有关了。 起首,从 JDK1.2 开始,工具的引用被分别为4种级
副问题[/!--empirenews.page--]

之前我们提到过 GC,但当 Java 中引用的工具越来越多,会导致内存空间不敷,最终会发生错误 OutOfMemoryError,并让应用措施终止。那为什么 GC 在此时不能多网络一些工具呢?这就和本日说的引用范例有关了。

起首,从 JDK1.2 开始,工具的引用被分别为4种级别,从而使措施能越发机动地节制工具的生命周期。这4种级别由高到低依次为:强引用、软引用、弱引用和虚引用。

强引用

强引用(Strong Reference)是行使最广泛的引用。假如一个工具具有强引用,那么它永久不会被 GC。譬喻:

  1. Object strongReference = new Object(); 

当内存空间不敷时,JVM 甘愿抛出OutOfMemoryError,使措施非常终止,也不会靠随意接纳具有强引用的工具来办理内存不敷的题目。

假如强引用工具不行使时,必要弱化从而可以被 GC,譬喻ArrayList中的clear()要领:

  1. /** 
  2. * Removes all of the elements from this list. The list will 
  3. * be empty after this call returns. 
  4. */ 
  5. public void clear() { 
  6. modCount++; 
  7.  
  8. // clear to let GC do its work 
  9. for (int i = 0; i < size; i++) 
  10. elementData[i] = null; 
  11.  
  12. size = 0; 

显式地配置强引用工具为null,或让其超出工具的生命周期范畴,则垃圾接纳器以为该工具不存在引用,就会接纳这个工具。详细什么时辰网络这要取决于详细的垃圾接纳器。

软引用

假如一个工具只具有软引用(Soft Reference),当内存空间富裕时,垃圾接纳器就不会接纳它;假如内存空间不敷了,就会接纳这些工具的内存。只要垃圾接纳器没有接纳它,该工具就可以被措施行使。让我们来看一个例子详细相识一下:

  1. String str = new String("abc"); 
  2. SoftReference<String> softReference = new SoftReference<>(str); 
  3. String result = softReference.get(); 

让我们来看一下get():

  1. public T get() { 
  2. T o = super.get(); 
  3. // timestamp代表上一次软引用上一次被行使的时刻(初始化、get()) 
  4. // clock代表上一次GC的时刻 
  5. if (o != null && this.timestamp != clock) 
  6. this.timestamp = clock; 
  7. return o; 

因此,软引用在被垃圾接纳时,也遵循LRU法例,优先接纳最近起码被行使的工具举办接纳。

软引用的行使场景多是内存敏感的高速缓存。详细来说,就是我们但愿将数据存放到缓存中,这样可以快速举办读取。可是,当 JVM 中内存不足用时,我们又不但愿缓存数据会占用到 JVM 的内存。譬喻共同ReferenceQueue,假如软引用所引用工具被垃圾接纳,JVM 就会把这个软引用插手到与之关联的引用行列中:

  1. ReferenceQueue<String> referenceQueue = new ReferenceQueue<>(); 
  2. String str = new String("abc"); 
  3. SoftReference<String> softReference = new SoftReference<>(str, referenceQueue); 
  4.  
  5. str = null; 
  6. // Notify GC 
  7. System.gc(); 
  8.  
  9. System.out.println(softReference.get()); // abc 
  10.  
  11. Reference<? extends String> reference = referenceQueue.poll(); 
  12. System.out.println(reference); //null 

可是必要留意的是,假如行使软引用缓存,有也许导致Full GC增多。

弱引用

假如一个工具只具有弱引用(Weak Reference),其生命周期对比于软引用越发短暂。在垃圾接纳器线程扫描它所统领的内存地区的进程中,一旦发明白只具有弱引用的工具,不管当前内存空间足够与否,城市对它举办接纳。不外,因为垃圾接纳器是一个优先级很低的线程,因此不必然会很快发明那些只具有弱引用的工具。其行使为:

  1. String str = new String("abc"); 
  2. WeakReference<String> weakReference = new WeakReference<>(str); 
  3. str = weakReference.get(); 

讲到弱引用,就不得不提到WeakHashMap。和HashMap对比,当我们给 JVM 分派的内存不敷的时辰,HashMap 情愿抛出 OutOfMemoryError 非常,也不会接纳其响应的没有被引用的工具,而 WeakHashMap 则会接纳存储在个中但有被引用的工具。

WeakHashMap 通过将一些没有被引用的键的值赋值为 null ,这样的话就会奉告GC去接纳这些存储的值了。若是我们专程传入 key 为 null 的键,WeakHashMap 会将键配置为非凡的 Oject,源码为:

  1. public V put(K key, V value) { 
  2. // key会被从头赋值 
  3. Object k = maskNull(key); 
  4. int h = hash(k); 
  5. Entry<K,V>[] tab = getTable(); 
  6. int i = indexFor(h, tab.length); 
  7.  
  8. for (Entry<K,V> e = tab[i]; e != null; ee = e.next) { 
  9. if (h == e.hash && eq(k, e.get())) { 
  10. V oldValue = e.value; 
  11. if (value != oldValue) 
  12. e.value = value; 
  13. return oldValue; 
  14.  
  15. modCount++; 
  16. Entry<K,V> e = tab[i]; 
  17. tab[i] = new Entry<>(k, value, queue, h, e); 
  18. if (++size >= threshold) 
  19. resize(tab.length * 2); 
  20. return null; 
  21.  
  22. /** 
  23. * Value representing null keys inside tables. 
  24. * 非凡的key 
  25. */ 
  26. private static final Object NULL_KEY = new Object(); 
  27.  
  28. /** 
  29. * Use NULL_KEY for key if it is null. 
  30. */ 
  31. private static Object maskNull(Object key) { 
  32. return (key == null) ? NULL_KEY : key; 

虚引用

虚引用(PhantomReference),顾名思义,就是形同虚设。与其他几种引用都差异,虚引用并不会抉择工具的生命周期。假如一个工具仅持有虚引用,那么它就和没有任何引用一样,在任何时辰都也许被垃圾接纳器接纳。

虚引用首要用来跟踪工具被垃圾接纳器接纳的勾当。 虚引用与软引用和弱引用的一个区别在于:

(编辑:河北网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读