java.lang.ref.WeakReference和java.lang.ref.SoftReference有什么区别?
当前回答
在Java中;从强到弱依次为:强、软、弱、幻
强引用是一种普通引用,用于保护被引用的对象不被GC收集。即从不收集垃圾。
软引用可以被垃圾回收器收集,但可能直到需要它的内存时才会被收集。即在OutOfMemoryError之前进行垃圾收集。
弱引用是指不保护被引用对象不被GC收集的引用。即,当没有强或软引用时,垃圾收集。
幻影引用是在对象完成后,但在已分配的内存被回收之前,对对象的幻影引用。
源
类比:假设JVM是一个王国,对象是王国的国王,GC是王国的攻击者,试图杀死国王(对象)。
当国王强大时,GC不能杀死他。 当国王是软的,GC攻击他,但国王统治王国的保护,直到资源可用。 当国王虚弱时,GC攻击他,但在没有保护的情况下统治王国。 当国王是幻影时,GC已经杀死了他,但国王可以通过他的灵魂获得。
其他回答
WeakReference:只弱引用的对象将在每个GC周期(minor或full)收集。
SoftReference:当只被软引用的对象被收集时,取决于:
-XX:SoftRefLRUPolicyMSPerMB=N标志(默认值是1000,也就是1秒) 堆中的空闲内存量。 例子: 堆有10MB的空闲空间(在完全GC之后); - xx: SoftRefLRUPolicyMSPerMB = 1000 如果只被SoftReference引用的对象上次被访问的时间大于10秒,则该对象将被收集。
唯一真正的区别
根据文档,松散的weakreference必须由正在运行的GC清除。
根据文档,在抛出OOM之前必须清除松散的softreference。
这是唯一真正的区别。其他的都不是合同的一部分。(我假设最新的文件是合同文件。)
软引用很有用。内存敏感的缓存使用软引用,而不是弱引用。 WeakReference的唯一正确用法是观察GC运行。为此,您可以创建一个新的WeakReference,其对象立即超出作用域,然后尝试从weak_ref.get()中获取null。当它为空时,您可以了解到在此期间GC运行了。
关于WeakReference的错误使用,列表是无限的:
a lousy hack to implement priority-2 softreference such that you don't have to write one, yet it doesn't work as expected because the cache would be cleared on every GC run, even when there is spare memory. See https://stackoverflow.com/a/3243242/632951 for phails. (Besides, what if you need more than 2 levels of cache priority? You'd still gotta need a real library for it.) a lousy hack to associate data with an object of an existing class, yet it creates a memory leak (OutOfMemoryError) when your GC decides to take a break after your weakreferences are created. Besides, it's beyond ugly: A better approach is to use tuples. a lousy hack to associate data with an object of an existing class, where the class has the nerve to make itself non-subclassable, and is used in an existing function code which you need to call. In such a case, the proper solution is to either edit the class and make it subclassable, or edit the function and make it take an interface instead of a class, or use an alternative function.
应该注意,弱引用对象只有在只有弱引用时才会被收集。如果它有一个强引用,那么无论它有多少弱引用,它都不会被收集。
为了给出一个动态内存使用方面,我做了一个实验,在重物的重负载下,将强、软、弱和幻影引用保留到程序结束。然后监控堆使用和GC行为。这些指标可能因情况而异,但肯定能提供高层次的理解。以下是调查结果。
重负载下的堆和GC行为
Strong/Hard Reference - As program continued, JVM couldn't collect retained strong referenced object. Eventually ended up in "java.lang.OutOfMemoryError: Java heap space" Soft Reference - As program continued, heap usage kept growing, but OLD gen GC happened hen it was nearing max heap. GC started bit later in time after starting program. Weak Reference - As program started, objects started finalizing & getting collected almost immediately. Mostly objects got collected in young generation garbage collection. Phantom Reference - Similar to weak reference, phantom referenced objects also started getting finalized & garbage collected immediately. There were no old generation GC & all objects were getting collected in young generation garbage collection itself.
你可以在这里获得更多关于这个实验的深度图表、统计数据和观察结果。
在Java中;从强到弱依次为:强、软、弱、幻
强引用是一种普通引用,用于保护被引用的对象不被GC收集。即从不收集垃圾。
软引用可以被垃圾回收器收集,但可能直到需要它的内存时才会被收集。即在OutOfMemoryError之前进行垃圾收集。
弱引用是指不保护被引用对象不被GC收集的引用。即,当没有强或软引用时,垃圾收集。
幻影引用是在对象完成后,但在已分配的内存被回收之前,对对象的幻影引用。
源
类比:假设JVM是一个王国,对象是王国的国王,GC是王国的攻击者,试图杀死国王(对象)。
当国王强大时,GC不能杀死他。 当国王是软的,GC攻击他,但国王统治王国的保护,直到资源可用。 当国王虚弱时,GC攻击他,但在没有保护的情况下统治王国。 当国王是幻影时,GC已经杀死了他,但国王可以通过他的灵魂获得。
推荐文章
- 在流中使用Java 8 foreach循环移动到下一项
- 访问限制:'Application'类型不是API(必需库rt.jar的限制)
- 用Java计算两个日期之间的天数
- 如何配置slf4j-simple
- 在Jar文件中运行类
- 带参数的可运行?
- 我如何得到一个字符串的前n个字符而不检查大小或出界?
- 我可以在Java中设置enum起始值吗?
- Java中的回调函数
- c#和Java中的泛型有什么不同?和模板在c++ ?
- 在Java中,流相对于循环的优势是什么?
- Jersey在未找到InjectionManagerFactory时停止工作
- 在Java流是peek真的只是调试?
- Recyclerview不调用onCreateViewHolder
- 将JSON字符串转换为HashMap