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