//实际的数据对象,引用持有的实际对象
class Data {
private int id = 0;
public int getId() {
return id;
}@Override
public String toString() {
return "Data(" + id +")";
}
}//在使用弱引用时,一般会自定义其子类,加入一些自己的数据,如果本例
//加了一个id域,这里为了后续输出方便,重写了其toString方法
class MyRef extends WeakReference {private int id;
public MyRef(Data referent, ReferenceQueue
例1 如果还有强引用,则发生GC时,弱引用持有的对象不会被回收,弱引用本身也不会被放入引用队列
public class ReferenceQueueTest {
public static void main(String[] args) {
//实例化一个引用队列
ReferenceQueue
/**
* Represents the level of resource leak detection.
*/
public enum Level {
/**
* Disables resource leak detection.
*/
//关闭内存泄漏检测
DISABLED,
/**
* Enables simplistic sampling resource leak detection which reports there is a leak or not,
* at the cost of small overhead (default).
*/
//实现最简单的内存泄漏检测,没有任何信息输出,仅仅输出是否发生
//了内存泄漏,采用的ByteBuf包装类是
//SimpleLeakAwareCompositeByteBuf
SIMPLE,
/**
* Enables advanced sampling resource leak detection which reports where the leaked object was accessed
* recently at the cost of high overhead.
*/
//实现高级点的内存泄漏检测,发生泄漏时会同时打印出一些调用轨迹
//采用的ByteBuf包装类是AdvancedLeakAwareCompositeByteBuf
ADVANCED,
/**
* Enables paranoid resource leak detection which reports where the leaked object was accessed recently,
* at the cost of the highest possible overhead (for testing purposes only).
*/
//比较激进的内存泄漏检测,代价较高,一般用于测试,采用的ByteBuf
//包装类也是AdvancedLeakAwareCompositeByteBuf
PARANOID;
}
//SimpleLeakAwareCompositeByteBuf
@Override
public boolean release() {
if (super.release()) {
//引用计数为0,则清除弱引用
closeLeak();
return true;
}
return false;
}@Override
public boolean release(int decrement) {
if (super.release(decrement)) {
//引用计数为0,则清除弱引用
closeLeak();
return true;
}
return false;
}private void closeLeak() {
// Close the ResourceLeakTracker with the tracked ByteBuf as argument. This must be the same that was used when
// calling DefaultResourceLeak.track(...).
boolean closed = leak.close(trackedByteBuf);
assert closed;
}//DefaultResourceLeak
@Override
public boolean close() {
// Use the ConcurrentMap remove method, which avoids allocating an iterator.
if (allLeaks.remove(this, LeakEntry.INSTANCE)) {
//显示清空该弱引用持有的实际对象,所以该弱引用自身不会
//在GC时被加入应用队列
// Call clear so the reference is not even enqueued.
clear();
headUpdater.set(this, null);
return true;
}
return false;
}
//ResourceLeakDetector
private void reportLeak() {
//汇报内存检测需要日志启用error级别
//没有启用则清空引用队列并返回
if (!logger.isErrorEnabled()) {
clearRefQueue();
return;
}// Detect and report previous leaks.
//依次取出引用队列中的所有弱引用进行输出
for (;
;
) {
@SuppressWarnings("unchecked")
DefaultResourceLeak ref = (DefaultResourceLeak) refQueue.poll();
if (ref == null) {
break;
}if (!ref.dispose()) {
continue;
}//调用弱引用DefaultResourceLeak的toString方法,
//其实主要是返回其record记录的调用轨迹信息
String records = ref.toString();
//汇报过的放入reportedLeaks进行记录
if (reportedLeaks.putIfAbsent(records, Boolean.TRUE) == null) {
//如果ByteBuf没有调用过record方法(比如Level.SIMPLE使用
//的SimpleLeakAwareCompositeByteBuf就不会调用record方法
//或者使用AdvancedLeakAwareCompositeByteBuf但是没有显示
//调用过其record方法
if (records.isEmpty()) {
reportUntracedLeak(resourceType);
} else {
reportTracedLeak(resourceType, records);
}
}
}
}/**
* This method is called when an untraced leak is detected. It can be overridden for tracking how many times leaks
* have been detected.
*/
//没有调用轨迹的,就直接打印出内存泄漏的简单信息
protected void reportUntracedLeak(String resourceType) {
logger.error("LEAK: {}.release() was not called before it's garbage-collected. " +
"Enable advanced leak reporting to find out where the leak occurred. " +
"To enable advanced leak reporting, " +
"specify the JVM option '-D{}={}' or call {}.setLevel() " +
"See http://netty.io/wiki/reference-counted-objects.html for more information.",
resourceType, PROP_LEVEL, Level.ADVANCED.name().toLowerCase(), simpleClassName(this));
}/**
* This method is called when a traced leak is detected. It can be overridden for tracking how many times leaks
* have been detected.
*/
//有调用轨迹的,会同时打印出调用轨迹信息
protected void reportTracedLeak(String resourceType, String records) {
logger.error(
"LEAK: {}.release() was not called before it's garbage-collected. " +
"See http://netty.io/wiki/reference-counted-objects.html for more information.{}",
resourceType, records);
}