得物.apk(点击下载) / ResourceLeakDetector.java
package io.netty.util;
import androidx.core.view.accessibility.AccessibilityEventCompat;
import g00.a;
import io.netty.util.internal.EmptyArrays;
import io.netty.util.internal.PlatformDependent;
import io.netty.util.internal.StringUtil;
import io.netty.util.internal.SystemPropertyUtil;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
public class ResourceLeakDetector<T> {
public static final Level DEFAULT_LEVEL;
public static final int SAMPLING_INTERVAL = SystemPropertyUtil.getInt("io.netty.leakDetection.samplingInterval", 128);
public static final int TARGET_RECORDS;
public static final AtomicReference<String[]> excludedMethods = new AtomicReference<>(EmptyArrays.EMPTY_STRINGS);
private static Level level;
private static final InternalLogger logger;
private final Set<DefaultResourceLeak<?>> allLeaks;
private final ReferenceQueue<Object> refQueue;
private final ConcurrentMap<String, Boolean> reportedLeaks;
private final String resourceType;
private final int samplingInterval;
public static final class DefaultResourceLeak<T> extends WeakReference<Object> implements ResourceLeakTracker<T>, ResourceLeak {
public static final /* synthetic */ boolean $assertionsDisabled = false;
private static final AtomicIntegerFieldUpdater<DefaultResourceLeak<?>> droppedRecordsUpdater = AtomicIntegerFieldUpdater.newUpdater(DefaultResourceLeak.class, "droppedRecords");
private static final AtomicReferenceFieldUpdater<DefaultResourceLeak<?>, Record> headUpdater = AtomicReferenceFieldUpdater.newUpdater(DefaultResourceLeak.class, Record.class, "head");
private final Set<DefaultResourceLeak<?>> allLeaks;
private volatile int droppedRecords;
private volatile Record head;
private final int trackedHash;
public DefaultResourceLeak(Object obj, ReferenceQueue<Object> referenceQueue, Set<DefaultResourceLeak<?>> set) {
super(obj, referenceQueue);
this.trackedHash = System.identityHashCode(obj);
set.add(this);
headUpdater.set(this, new Record(Record.BOTTOM));
this.allLeaks = set;
}
private static void reachabilityFence0(Object obj) {
if (obj != null) {
synchronized (obj) {
}
}
}
private void record0(Object obj) {
boolean z;
Record record;
boolean z4;
Record record2;
if (ResourceLeakDetector.TARGET_RECORDS > 0) {
do {
AtomicReferenceFieldUpdater<DefaultResourceLeak<?>, Record> atomicReferenceFieldUpdater = headUpdater;
Record record3 = atomicReferenceFieldUpdater.get(this);
if (record3 != null) {
z = true;
int i = record3.pos + 1;
int i3 = ResourceLeakDetector.TARGET_RECORDS;
if (i >= i3) {
z4 = PlatformDependent.threadLocalRandom().nextInt(1 << Math.min(i - i3, 30)) != 0;
record = z4 ? record3.next : record3;
} else {
record = record3;
z4 = false;
}
if (obj == null) {
record2 = new Record(record);
}
while (true) {
if (!atomicReferenceFieldUpdater.compareAndSet(this, record3, record2)) {
if (atomicReferenceFieldUpdater.get(this) != record3) {
z = false;
continue;
break;
}
} else {
break;
}
}
} else {
return;
}
} while (!z);
if (z4) {
droppedRecordsUpdater.incrementAndGet(this);
}
}
}
@Override // io.netty.util.ResourceLeak
public boolean close() {
if (!this.allLeaks.remove(this)) {
return false;
}
clear();
headUpdater.set(this, null);
return true;
}
public boolean dispose() {
clear();
return this.allLeaks.remove(this);
}
@Override // io.netty.util.ResourceLeakTracker, io.netty.util.ResourceLeak
public void record() {
record0(null);
}
public String toString() {
Record andSet = headUpdater.getAndSet(this, null);
if (andSet == null) {
return "";
}
int i = droppedRecordsUpdater.get(this);
int i3 = 0;
int i12 = 1;
int i13 = andSet.pos + 1;
StringBuilder sb2 = new StringBuilder(i13 * AccessibilityEventCompat.TYPE_WINDOW_CONTENT_CHANGED);
String str = StringUtil.NEWLINE;
sb2.append(str);
sb2.append("Recent access records: ");
sb2.append(str);
HashSet hashSet = new HashSet(i13);
while (true) {
Record record = Record.BOTTOM;
if (andSet == record) {
break;
}
String record2 = andSet.toString();
if (!hashSet.add(record2)) {
i3++;
} else if (andSet.next == record) {
sb2.append("Created at:");
sb2.append(StringUtil.NEWLINE);
sb2.append(record2);
} else {
sb2.append('#');
sb2.append(i12);
sb2.append(':');
sb2.append(StringUtil.NEWLINE);
sb2.append(record2);
i12++;
}
andSet = andSet.next;
}
if (i3 > 0) {
a.r(sb2, ": ", i3, " leak records were discarded because they were duplicates");
sb2.append(StringUtil.NEWLINE);
}
if (i > 0) {
a.r(sb2, ": ", i, " leak records were discarded because the leak record count is targeted to ");
sb2.append(ResourceLeakDetector.TARGET_RECORDS);
sb2.append(". Use system property ");
sb2.append("io.netty.leakDetection.targetRecords");
sb2.append(" to increase the limit.");
sb2.append(StringUtil.NEWLINE);
}
sb2.setLength(sb2.length() - StringUtil.NEWLINE.length());
return sb2.toString();
}
@Override // io.netty.util.ResourceLeakTracker, io.netty.util.ResourceLeak
public void record(Object obj) {
record0(obj);
}
@Override // io.netty.util.ResourceLeakTracker
public boolean close(T t) {
try {
return close();
} finally {
reachabilityFence0(t);
}
}
}
public enum Level {
DISABLED,
SIMPLE,
ADVANCED,
PARANOID;
public static Level parseLevel(String str) {
String trim = str.trim();
Level[] values = values();
for (Level level : values) {
if (trim.equalsIgnoreCase(level.name()) || trim.equals(String.valueOf(level.ordinal()))) {
return level;
}
}
return ResourceLeakDetector.DEFAULT_LEVEL;
}
}
static {
Level level2 = Level.SIMPLE;
DEFAULT_LEVEL = level2;
InternalLogger instance = InternalLoggerFactory.getInstance(ResourceLeakDetector.class);
logger = instance;
boolean z = false;
if (SystemPropertyUtil.get("io.netty.noResourceLeakDetection") != null) {
z = SystemPropertyUtil.getBoolean("io.netty.noResourceLeakDetection", false);
instance.debug("-Dio.netty.noResourceLeakDetection: {}", Boolean.valueOf(z));
instance.warn("-Dio.netty.noResourceLeakDetection is deprecated. Use '-D{}={}' instead.", "io.netty.leakDetection.level", level2.name().toLowerCase());
}
if (z) {
level2 = Level.DISABLED;
}
Level parseLevel = Level.parseLevel(SystemPropertyUtil.get("io.netty.leakDetection.level", SystemPropertyUtil.get("io.netty.leakDetectionLevel", level2.name())));
int i = SystemPropertyUtil.getInt("io.netty.leakDetection.targetRecords", 4);
TARGET_RECORDS = i;
level = parseLevel;
if (instance.isDebugEnabled()) {
instance.debug("-D{}: {}", "io.netty.leakDetection.level", parseLevel.name().toLowerCase());
instance.debug("-D{}: {}", "io.netty.leakDetection.targetRecords", Integer.valueOf(i));
}
}
@Deprecated
public ResourceLeakDetector(Class<?> cls) {
this(StringUtil.simpleClassName(cls));
}
public static void addExclusions(Class cls, String... strArr) {
String[] strArr2;
String[] strArr3;
HashSet hashSet = new HashSet(Arrays.asList(strArr));
Method[] declaredMethods = cls.getDeclaredMethods();
int length = declaredMethods.length;
int i = 0;
while (i < length && (!hashSet.remove(declaredMethods[i].getName()) || !hashSet.isEmpty())) {
i++;
}
if (hashSet.isEmpty()) {
do {
strArr2 = excludedMethods.get();
strArr3 = (String[]) Arrays.copyOf(strArr2, (strArr.length * 2) + strArr2.length);
for (int i3 = 0; i3 < strArr.length; i3++) {
int i12 = i3 * 2;
strArr3[strArr2.length + i12] = cls.getName();
strArr3[strArr2.length + i12 + 1] = strArr[i3];
}
} while (!excludedMethods.compareAndSet(strArr2, strArr3));
return;
}
StringBuilder sb2 = new StringBuilder();
sb2.append("Can't find '");
sb2.append(hashSet);
sb2.append("' in ");
throw new IllegalArgumentException(androidx.appcompat.widget.a.h(cls, sb2));
}
private void clearRefQueue() {
while (true) {
DefaultResourceLeak defaultResourceLeak = (DefaultResourceLeak) this.refQueue.poll();
if (defaultResourceLeak != null) {
defaultResourceLeak.dispose();
} else {
return;
}
}
}
public static Level getLevel() {
return level;
}
public static boolean isEnabled() {
return getLevel().ordinal() > Level.DISABLED.ordinal();
}
private void reportLeak() {
if (!logger.isErrorEnabled()) {
clearRefQueue();
return;
}
while (true) {
DefaultResourceLeak defaultResourceLeak = (DefaultResourceLeak) this.refQueue.poll();
if (defaultResourceLeak != null) {
if (defaultResourceLeak.dispose()) {
String defaultResourceLeak2 = defaultResourceLeak.toString();
if (this.reportedLeaks.putIfAbsent(defaultResourceLeak2, Boolean.TRUE) == null) {
if (defaultResourceLeak2.isEmpty()) {
reportUntracedLeak(this.resourceType);
} else {
reportTracedLeak(this.resourceType, defaultResourceLeak2);
}
}
}
} else {
return;
}
}
}
@Deprecated
public static void setEnabled(boolean z) {
setLevel(z ? Level.SIMPLE : Level.DISABLED);
}
public static void setLevel(Level level2) {
level = level2;
}
private DefaultResourceLeak track0(T t) {
Level level2 = level;
if (level2 == Level.DISABLED) {
return null;
}
if (level2.ordinal() >= Level.PARANOID.ordinal()) {
reportLeak();
return new DefaultResourceLeak(t, this.refQueue, this.allLeaks);
} else if (PlatformDependent.threadLocalRandom().nextInt(this.samplingInterval) != 0) {
return null;
} else {
reportLeak();
return new DefaultResourceLeak(t, this.refQueue, this.allLeaks);
}
}
@Deprecated
public final ResourceLeak open(T t) {
return track0(t);
}
@Deprecated
public void reportInstancesLeak(String str) {
}
public void reportTracedLeak(String str, String str2) {
logger.error("LEAK: {}.release() was not called before it's garbage-collected. See http://netty.io/wiki/reference-counted-objects.html for more information.{}", str, str2);
}
public void reportUntracedLeak(String str) {
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.", str, "io.netty.leakDetection.level", Level.ADVANCED.name().toLowerCase(), StringUtil.simpleClassName(this));
}
public final ResourceLeakTracker<T> track(T t) {
return track0(t);
}
@Deprecated
public ResourceLeakDetector(String str) {
this(str, 128, Long.MAX_VALUE);
}
@Deprecated
public ResourceLeakDetector(Class<?> cls, int i, long j) {
this(cls, i);
}
public static final class Record extends Throwable {
public static final Record BOTTOM = new Record();
private static final long serialVersionUID = 6065153674892850720L;
private final String hintString;
public final Record next;
public final int pos;
public Record(Record record, Object obj) {
this.hintString = obj instanceof ResourceLeakHint ? ((ResourceLeakHint) obj).toHintString() : obj.toString();
this.next = record;
this.pos = record.pos + 1;
}
public String toString() {
StringBuilder sb2 = new StringBuilder((int) AccessibilityEventCompat.TYPE_WINDOW_CONTENT_CHANGED);
if (this.hintString != null) {
sb2.append("\tHint: ");
sb2.append(this.hintString);
sb2.append(StringUtil.NEWLINE);
}
StackTraceElement[] stackTrace = getStackTrace();
for (int i = 3; i < stackTrace.length; i++) {
StackTraceElement stackTraceElement = stackTrace[i];
String[] strArr = ResourceLeakDetector.excludedMethods.get();
int i3 = 0;
while (true) {
if (i3 >= strArr.length) {
sb2.append('\t');
sb2.append(stackTraceElement.toString());
sb2.append(StringUtil.NEWLINE);
break;
}
if (strArr[i3].equals(stackTraceElement.getClassName()) && strArr[i3 + 1].equals(stackTraceElement.getMethodName())) {
break;
}
i3 += 2;
}
}
return sb2.toString();
}
public Record(Record record) {
this.next = record;
this.pos = record.pos + 1;
}
private Record() {
this.pos = -1;
}
}
public ResourceLeakDetector(Class<?> cls, int i) {
this(StringUtil.simpleClassName(cls), i, Long.MAX_VALUE);
}
@Deprecated
public ResourceLeakDetector(String str, int i, long j) {
this.allLeaks = Collections.newSetFromMap(new ConcurrentHashMap());
this.refQueue = new ReferenceQueue<>();
this.reportedLeaks = PlatformDependent.newConcurrentHashMap();
this.resourceType = str;
this.samplingInterval = i;
}
}