1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package io.netty.util;
18
19 import io.netty.util.internal.ObjectUtil;
20 import io.netty.util.internal.PlatformDependent;
21 import io.netty.util.internal.SystemPropertyUtil;
22 import io.netty.util.internal.logging.InternalLogger;
23 import io.netty.util.internal.logging.InternalLoggerFactory;
24
25 import java.lang.reflect.Constructor;
26
27
28
29
30 public abstract class ResourceLeakDetectorFactory {
31 private static final InternalLogger logger = InternalLoggerFactory.getInstance(ResourceLeakDetectorFactory.class);
32
33 private static volatile ResourceLeakDetectorFactory factoryInstance = new DefaultResourceLeakDetectorFactory();
34
35
36
37
38
39
40 public static ResourceLeakDetectorFactory instance() {
41 return factoryInstance;
42 }
43
44
45
46
47
48
49
50
51 public static void setResourceLeakDetectorFactory(ResourceLeakDetectorFactory factory) {
52 factoryInstance = ObjectUtil.checkNotNull(factory, "factory");
53 }
54
55
56
57
58
59
60
61
62 public final <T> ResourceLeakDetector<T> newResourceLeakDetector(Class<T> resource) {
63 return newResourceLeakDetector(resource, ResourceLeakDetector.SAMPLING_INTERVAL);
64 }
65
66
67
68
69
70
71
72
73
74
75
76
77 @Deprecated
78 public abstract <T> ResourceLeakDetector<T> newResourceLeakDetector(
79 Class<T> resource, int samplingInterval, long maxActive);
80
81
82
83
84
85
86
87
88
89 @SuppressWarnings("deprecation")
90 public <T> ResourceLeakDetector<T> newResourceLeakDetector(Class<T> resource, int samplingInterval) {
91 ObjectUtil.checkPositive(samplingInterval, "samplingInterval");
92 return newResourceLeakDetector(resource, samplingInterval, Long.MAX_VALUE);
93 }
94
95
96
97
98 private static final class DefaultResourceLeakDetectorFactory extends ResourceLeakDetectorFactory {
99 private final Constructor<?> obsoleteCustomClassConstructor;
100 private final Constructor<?> customClassConstructor;
101
102 DefaultResourceLeakDetectorFactory() {
103 String customLeakDetector;
104 try {
105 customLeakDetector = SystemPropertyUtil.get("io.netty.customResourceLeakDetector");
106 } catch (Throwable cause) {
107 logger.error("Could not access System property: io.netty.customResourceLeakDetector", cause);
108 customLeakDetector = null;
109 }
110 if (customLeakDetector == null) {
111 obsoleteCustomClassConstructor = customClassConstructor = null;
112 } else {
113 obsoleteCustomClassConstructor = obsoleteCustomClassConstructor(customLeakDetector);
114 customClassConstructor = customClassConstructor(customLeakDetector);
115 }
116 }
117
118 private static Constructor<?> obsoleteCustomClassConstructor(String customLeakDetector) {
119 try {
120 final Class<?> detectorClass = Class.forName(customLeakDetector, true,
121 PlatformDependent.getSystemClassLoader());
122
123 if (ResourceLeakDetector.class.isAssignableFrom(detectorClass)) {
124 return detectorClass.getConstructor(Class.class, int.class, long.class);
125 } else {
126 logger.error("Class {} does not inherit from ResourceLeakDetector.", customLeakDetector);
127 }
128 } catch (Throwable t) {
129 logger.error("Could not load custom resource leak detector class provided: {}",
130 customLeakDetector, t);
131 }
132 return null;
133 }
134
135 private static Constructor<?> customClassConstructor(String customLeakDetector) {
136 try {
137 final Class<?> detectorClass = Class.forName(customLeakDetector, true,
138 PlatformDependent.getSystemClassLoader());
139
140 if (ResourceLeakDetector.class.isAssignableFrom(detectorClass)) {
141 return detectorClass.getConstructor(Class.class, int.class);
142 } else {
143 logger.error("Class {} does not inherit from ResourceLeakDetector.", customLeakDetector);
144 }
145 } catch (Throwable t) {
146 logger.error("Could not load custom resource leak detector class provided: {}",
147 customLeakDetector, t);
148 }
149 return null;
150 }
151
152 @SuppressWarnings("deprecation")
153 @Override
154 public <T> ResourceLeakDetector<T> newResourceLeakDetector(Class<T> resource, int samplingInterval,
155 long maxActive) {
156 if (obsoleteCustomClassConstructor != null) {
157 try {
158 @SuppressWarnings("unchecked")
159 ResourceLeakDetector<T> leakDetector =
160 (ResourceLeakDetector<T>) obsoleteCustomClassConstructor.newInstance(
161 resource, samplingInterval, maxActive);
162 logger.debug("Loaded custom ResourceLeakDetector: {}",
163 obsoleteCustomClassConstructor.getDeclaringClass().getName());
164 return leakDetector;
165 } catch (Throwable t) {
166 logger.error(
167 "Could not load custom resource leak detector provided: {} with the given resource: {}",
168 obsoleteCustomClassConstructor.getDeclaringClass().getName(), resource, t);
169 }
170 }
171
172 ResourceLeakDetector<T> resourceLeakDetector = new ResourceLeakDetector<T>(resource, samplingInterval,
173 maxActive);
174 logger.debug("Loaded default ResourceLeakDetector: {}", resourceLeakDetector);
175 return resourceLeakDetector;
176 }
177
178 @Override
179 public <T> ResourceLeakDetector<T> newResourceLeakDetector(Class<T> resource, int samplingInterval) {
180 if (customClassConstructor != null) {
181 try {
182 @SuppressWarnings("unchecked")
183 ResourceLeakDetector<T> leakDetector =
184 (ResourceLeakDetector<T>) customClassConstructor.newInstance(resource, samplingInterval);
185 logger.debug("Loaded custom ResourceLeakDetector: {}",
186 customClassConstructor.getDeclaringClass().getName());
187 return leakDetector;
188 } catch (Throwable t) {
189 logger.error(
190 "Could not load custom resource leak detector provided: {} with the given resource: {}",
191 customClassConstructor.getDeclaringClass().getName(), resource, t);
192 }
193 }
194
195 ResourceLeakDetector<T> resourceLeakDetector = new ResourceLeakDetector<T>(resource, samplingInterval);
196 logger.debug("Loaded default ResourceLeakDetector: {}", resourceLeakDetector);
197 return resourceLeakDetector;
198 }
199 }
200 }