JDK1.8 动态代理机制及源码解析
动态代理
a) jdk 动态代理 Proxy,
核心思想:通过实现被代理类的所有接口,生成一个字节码文件后构造一个代理对象,通过持有反射构造被代理类的一个实例,再通过invoke反射调用被代理类实例的方法,来实现代理。
缺点:被代理类必须实现一个或多个接口
参考链接:http://rejoy.iteye.com/blog/1627405
源码解析:见第四部分
cglib 动态代理
核心思想:通过生成子类字节码实现,代理类为每个委托方法都生成两个方法,以add方法为例,一个是重写的add方法,一个是CGLIB$add$0方法,该方法直接调用委托类的add方法;
底层:使用一个小而快的字节码处理框架ASM(Java字节码操控框架),来转换字节码并生成新的类
缺点:不能代理final修饰的类,
参考链接:http://blog.csdn.net/yakoo5/article/details/9099133/
1
2
3
4
AOP实现机制
a. 实现方式:cglib 和 jdk自带的Proxy实现
b. 策略:
1)如果是有接口声明的类进行AOP 时,spring调用的是Java.lang.reflection.Proxy 类来做处理
2)如果是没有接口声明的类时, spring通过cglib包和内部类来实现
c.配置:
<aop:aspectj-autoproxy proxy-target-class="true" />配置了这句话的话就会强制使用cglib代理。 默认就是false
1
2
3
4
5
6
JDK动态代理Demo
//业务类接口
public interface MyBusinessInterface{
public void processBusiness();
}
//业务实现类
public class MyBusinessInterfaceImpl implements MyBusinessInterface {
public void processBusiness() {
System.out.println("processing business.....");
}
}
//被代理对象调用处理程序,必须实现InvocationHandler接口
public class MyInvocationHandler implements InvocationHandler {
//所代理的真实对象
private Object target = null;
//构造器,用于传入所代理的真实对象
MyInvocationHandler(Object target){
this.target = target;
}
//需要我们实现具体业务的地方
//proxy: 所生成代理类实例
//method: 指代的是我们所要调用真实对象的某个方法的Method对象
//args: 指代的是调用真实对象某个方法时接受的参数
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("You can do something here before process your business");
//调用目标对象的方法
Object result = method.invoke(target, args);
System.out.println("You can do something here after process your business");
//返回处理结果
return result;
}
}
//测试用例
public class Test {
public static void main(String[] args) {
//被代理真实对象
MyBusinessInterfaceImpl bpimpl = new MyBusinessInterfaceImpl();
//被代理对象调用处理程序,需传入被代理对象
MyInvocationHandler handler = new MyInvocationHandler(bpimpl);
//生成代理类实例
MyBusinessInterface bp = (MyBusinessInterface)Proxy.newProxyInstance(bpimpl.getClass().getClassLoader(), bpimpl.getClass().getInterfaces(), handler);
//调用processBusiness
bp.processBusiness();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
JDK1.8动态代理源码解析
Proxy解析
//代理类
public class Proxy implements java.io.Serializable {
private static final long serialVersionUID = -2222568056686623797L;
//代理类构造函数的参数类型
private static final Class<?>[] constructorParams =
{ InvocationHandler.class };
//代理类缓存
private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
//此代理实例的调用处理程序。
protected InvocationHandler h;
private Proxy() {
}
//代理类构造函数,参数类型:constructorParams所指定
protected Proxy(InvocationHandler h) {
Objects.requireNonNull(h);
this.h = h;
}
//获取目标代理类Class对象,需传入类加载器loader对象和被代理类实现接口数组interfaces随想
@CallerSensitive
public static Class<?> getProxyClass(ClassLoader loader,Class<?>... interfaces)
throws IllegalArgumentException{
//拷贝接口数组
final Class<?>[] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
//校验代理类的访问问权限
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
//获取代理类Class对象
return getProxyClass0(loader, intfs);
}
//校验代理类的访问问权限,这一块比较底层,我也不明白
private static void checkProxyAccess(Class<?> caller, ClassLoader loader, Class<?>... interfaces){
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
//获取调用者类的类加载器
ClassLoader ccl = caller.getClassLoader();
if (VM.isSystemDomainLoader(loader) && !VM.isSystemDomainLoader(ccl)) {
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
}
ReflectUtil.checkProxyPackageAccess(ccl, interfaces);
}
}
//获取代理类的Clas对象
private static Class<?> getProxyClass0(ClassLoader loader,
Class<?>... interfaces) {
if (interfaces.length > 65535) {
throw new IllegalArgumentException("interface limit exceeded");
}
//如果存在给定接口的给定装入器定义的代理类存在,则只返回缓存的副本;
//否则,它将通过proxyclassfactory创建代理类
//jdk1.8后收敛到这里 生成代理类字节码过程: ProxyClassFactory中了
return proxyClassCache.get(loader, interfaces);
}
//用于带有0个实现接口的代理类的key键值
private static final Object key0 = new Object();
/*
* Key1 and Key2 are optimized for the common use of dynamic proxies
* that implement 1 or 2 interfaces.
*/
/*
* a key used for proxy class with 1 implemented interface
*/
//用于带有1个实现接口的代理类的key键值
private static final class Key1 extends WeakReference<Class<?>> {
private final int hash;
Key1(Class<?> intf) {
super(intf);
this.hash = intf.hashCode();
}
@Override
public int hashCode() {
return hash;
}
@Override
public boolean equals(Object obj) {
Class<?> intf;
return this == obj ||
obj != null &&
obj.getClass() == Key1.class &&
(intf = get()) != null &&
intf == ((Key1) obj).get();
}
}
// //用于带有2个实现接口的代理类的key键值
private static final class Key2 extends WeakReference<Class<?>> {
private final int hash;
//弱引用对象:存放第二个接口类对象
private final WeakReference<Class<?>> ref2;
Key2(Class<?> intf1, Class<?> intf2) {
super(intf1);
hash = 31 * intf1.hashCode() + intf2.hashCode();
ref2 = new WeakReference<Class<?>>(intf2);
}
@Override
public int hashCode() {
return hash;
}
@Override
public boolean equals(Object obj) {
Class<?> intf1, intf2;
return this == obj ||
obj != null &&
obj.getClass() == Key2.class &&
(intf1 = get()) != null &&
intf1 == ((Key2) obj).get() &&
(intf2 = ref2.get()) != null &&
intf2 == ((Key2) obj).ref2.get();
}
}
// 这里用于带有>=3个实现接口的代理类的key键值(可以当实现任意数目接口的代理的key)
private static final class KeyX {
//接口数组对象的hash值
private final int hash;
//弱引用对象数组:存放表示接口的类对象数组
private final WeakReference<Class<?>>[] refs;
@SuppressWarnings("unchecked")
KeyX(Class<?>[] interfaces) {
hash = Arrays.hashCode(interfaces);
//构造一个弱引用对象数组
refs = (WeakReference<Class<?>>[])new WeakReference<?>[interfaces.length];
for (int i = 0; i < interfaces.length; i++) {
refs[i] = new WeakReference<>(interfaces[i]);
}
}
@Override
public int hashCode() {
return hash;
}
@Override
public boolean equals(Object obj) {
return this == obj ||
obj != null &&
obj.getClass() == KeyX.class &&
equals(refs, ((KeyX) obj).refs);
}
private static boolean equals(WeakReference<Class<?>>[] refs1,
WeakReference<Class<?>>[] refs2) {
//长度是否相等
if (refs1.length != refs2.length) {
return false;
}
//弱引用对象数组内接口类是否相同
for (int i = 0; i < refs1.length; i++) {
Class<?> intf = refs1[i].get();
if (intf == null || intf != refs2[i].get()) {
return false;
}
}
return true;
}
}
//将接口数组映射到一个最佳键的函数,其中表示接口的类对象为弱引用。
private static final class KeyFactory
implements BiFunction<ClassLoader, Class<?>[], Object>
{
@Override
public Object apply(ClassLoader classLoader, Class<?>[] interfaces) {
switch (interfaces.length) {
case 1: return new Key1(interfaces[0]); // the most frequent
case 2: return new Key2(interfaces[0], interfaces[1]);
case 0: return key0;
default: return new KeyX(interfaces);
}
}
}
//一个工厂函数生成‘给定类装载器和接口数组的代理类’。
private static final class ProxyClassFactory
implements BiFunction<ClassLoader, Class<?>[], Class<?>>
{
//所有代理类名称的前缀
private static final String proxyClassNamePrefix = "$Proxy";
//用于生成唯一代理类名称的下一个数字
private static final AtomicLong nextUniqueNumber = new AtomicLong();
@Override
public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {
Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
for (Class<?> intf : interfaces) {
//验证intf接口类Class对象是否为给定的classloder解析的
Class<?> interfaceClass = null;
try {
//指定类加载器获取接口类class对象,
interfaceClass = Class.forName(intf.getName(), false, loader);
} catch (ClassNotFoundException e) {
}
//验证是否为同一个接口类对象,
if (interfaceClass != intf) {
throw new IllegalArgumentException(
intf + " is not visible from class loader");
}
//验证类对象是否为接口
if (!interfaceClass.isInterface()) {
throw new IllegalArgumentException(
interfaceClass.getName() + " is not an interface");
}
/*
* Verify that this interface is not a duplicate.
* 验证此接口不是副本。
*/
if (interfaceSet.put(interfaceClass, Boolean.TRUE) != null) {
throw new IllegalArgumentException(
"repeated interface: " + interfaceClass.getName());
}
}
//定义代理类的包
String proxyPkg = null;
//定义代理类的修饰符:public和final类型
int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
/*
* Record the package of a non-public proxy interface so that the
* proxy class will be defined in the same package. Verify that
* all non-public proxy interfaces are in the same package.
* 记录一个非公共代理接口的包,以便在同一个包中定义代理类。验证所有非公共代理接口都在同一个包中。
*/
for (Class<?> intf : interfaces) {
//获取修饰符
int flags = intf.getModifiers();
if (!Modifier.isPublic(flags)) { //不是public修饰符
//则定义代理类的修饰符符:final
accessFlags = Modifier.FINAL;
//获取接口类名称,如:com.text.MyInterface
String name = intf.getName();
int n = name.lastIndexOf('.');
//获取包名,如:com.text
String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
if (proxyPkg == null) {
//获取包名称
proxyPkg = pkg;
} else if (!pkg.equals(proxyPkg)) { //interfaces含有来自不同包的非公共接口,抛错
throw new IllegalArgumentException(
"non-public interfaces from different packages");
}
}
}
if (proxyPkg == null) {
//如果没有非公开的代理接口,使用com.sun.proxy作为包名称
proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
}
//选择要生成的代理类的名称。
long num = nextUniqueNumber.getAndIncrement();
String proxyName = proxyPkg + proxyClassNamePrefix + num;
//真正生成指定的代理类字节码的地方
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
try {
//生成Calss对象
return defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length);
} catch (ClassFormatError e) {
/*
* A ClassFormatError here means that (barring bugs in the
* proxy class generation code) there was some other
* invalid aspect of the arguments supplied to the proxy
* class creation (such as virtual machine limitations
* exceeded).
*/
throw new IllegalArgumentException(e.toString());
}
}
}
//生成代理类对象
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
throws IllegalArgumentException {
//调用处理程序不能为空
Objects.requireNonNull(h);
//拷贝接口数组对象
final Class<?>[] intfs = interfaces.clone();
final SecurityManager sm = System.getSecurityManager();
if (sm != null) {
checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
}
//查找或生成指定的代理类。
Class<?> cl = getProxyClass0(loader, intfs);
/*
* Invoke its constructor with the designated invocation handler.
* 调用指定的调用处理程序的构造函数
*/
try {
if (sm != null) {
//校验新代理类的权限
checkNewProxyPermission(Reflection.getCallerClass(), cl);
}
//获取代理类构造函数,参数类型必须为InvocationHandler
final Constructor<?> cons = cl.getConstructor(constructorParams);
final InvocationHandler ih = h;
//构造函数不是public,则设置当前构造函数为访问权限
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
//调用构造函数构造代理类实例,入参数为‘调用处理程序’的实例,看到这里应该就明白jdk怎么实现动态代理的吧!
return cons.newInstance(new Object[]{h});
} catch (IllegalAccessException|InstantiationException e) {
throw new InternalError(e.toString(), e);
} catch (InvocationTargetException e) {
Throwable t = e.getCause();
if (t instanceof RuntimeException) {
throw (RuntimeException) t;
} else {
throw new InternalError(t.toString(), t);
}
} catch (NoSuchMethodException e) {
throw new InternalError(e.toString(), e);
}
}
private static void checkNewProxyPermission(Class<?> caller, Class<?> proxyClass) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
if (ReflectUtil.isNonPublicProxyClass(proxyClass)) {
//调用者类加载器
ClassLoader ccl = caller.getClassLoader();
//代理类的类加载器
ClassLoader pcl = proxyClass.getClassLoader();
// do permission check if the caller is in a different runtime package
// of the proxy class
//获取代理类的包名
int n = proxyClass.getName().lastIndexOf('.');
String pkg = (n == -1) ? "" : proxyClass.getName().substring(0, n);
//获取调用者包名
n = caller.getName().lastIndexOf('.');
String callerPkg = (n == -1) ? "" : caller.getName().substring(0, n);
//类加载不相同或包名不相同,校验权限
if (pcl != ccl || !pkg.equals(callerPkg)) {
sm.checkPermission(new ReflectPermission("newProxyInPackage." + pkg));
}
}
}
}
public static boolean isProxyClass(Class<?> cl) {
return Proxy.class.isAssignableFrom(cl) && proxyClassCache.containsValue(cl);
}
@CallerSensitive
public static InvocationHandler getInvocationHandler(Object proxy)
throws IllegalArgumentException
{
//验证该对象实际上是否为上一个代理实例。
if (!isProxyClass(proxy.getClass())) {
throw new IllegalArgumentException("not a proxy instance");
}
final Proxy p = (Proxy) proxy;
final InvocationHandler ih = p.h;
if (System.getSecurityManager() != null) {
Class<?> ihClass = ih.getClass();
Class<?> caller = Reflection.getCallerClass();
if (ReflectUtil.needsPackageAccessCheck(caller.getClassLoader(),
ihClass.getClassLoader()))
{
ReflectUtil.checkPackageAccess(ihClass);
}
}
return ih;
}
private static native Class<?> defineClass0(ClassLoader loader, String name,
byte[] b, int off, int len);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
WeakCache类解析 ####
//用处存放
final class WeakCache<K, P, V> {
private final ReferenceQueue<K> refQueue = new ReferenceQueue<>();
// the key type is Object for supporting null key
//Map<类加载器,Map<接口数组对象key,代理类工厂Factory或代理类包装对象LookupValue>
private final ConcurrentMap<Object, ConcurrentMap<Object, Supplier<V>>> map = new ConcurrentHashMap<>();
//存放当前key所对应的实例是否已经生成
private final ConcurrentMap<Supplier<V>, Boolean> reverseMap = new ConcurrentHashMap<>();
//生成key的工厂(对应上面的Key1-X类)
private final BiFunction<K, P, ?> subKeyFactory;
//生成value(代理类工厂,对应上面的ProxyClassFactory类)
private final BiFunction<K, P, V> valueFactory;
//构造方法,指定key和value工厂
public WeakCache(BiFunction<K, P, ?> subKeyFactory,
BiFunction<K, P, V> valueFactory) {
this.subKeyFactory = Objects.requireNonNull(subKeyFactory);
this.valueFactory = Objects.requireNonNull(valueFactory);
}
//获取缓存值,
public V get(K key, P parameter) {
//parameter不能weinull
Objects.requireNonNull(parameter);
//删除老节点
expungeStaleEntries();
Object cacheKey = CacheKey.valueOf(key, refQueue);
// lazily install the 2nd level valuesMap for the particular cacheKey
ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);
if (valuesMap == null) {
//添加cacheKey - ConcurrentMap<Object, Supplier<V>对象到map中
ConcurrentMap<Object, Supplier<V>> oldValuesMap = map.putIfAbsent(cacheKey,valuesMap = new ConcurrentHashMap<>());
if (oldValuesMap != null) {
valuesMap = oldValuesMap;
}
}
//利用subKeyFactory生成subKey
Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
//获取valuesMap中subKey所对应的值,此时为cachevalue <V>实例(步骤1:cachevalue <V>实例的来源)
Supplier<V> supplier = valuesMap.get(subKey);
Factory factory = null;
while (true) {
if (supplier != null) {
//步骤1:supplier可能是一个工厂对象或一个cachevalue <V>实例
V value = supplier.get();
if (value != null) {
return value;
}
}
// else no supplier in cache
// or a supplier that returned null (could be a cleared CacheValue
// or a Factory that wasn't successful in installing the CacheValue)
// lazily construct a Factory
if (factory == null) {
//构造一个工厂对象(步骤1:工厂对象的来源)
factory = new Factory(key, parameter, subKey, valuesMap);
}
//
if (supplier == null) {
//factory添加在valuesMap中
supplier = valuesMap.putIfAbsent(subKey, factory);
if (supplier == null) {
// 添加成功,则factory赋值给supplier,此时supplier为一个工厂对象
supplier = factory;
}
// else retry with winning supplier
//失败则重试
} else {
//将valuesMap中subKey所对应的值替换为factory
if (valuesMap.replace(subKey, supplier, factory)) {
// successfully replaced
// cleared CacheEntry / unsuccessful Factory
// with our Factory
supplier = factory;
} else {
// retry with current supplier
supplier = valuesMap.get(subKey);
}
}
}
}
/**
* Checks whether the specified non-null value is already present in this
* {@code WeakCache}. The check is made using identity comparison regardless
* of whether value's class overrides {@link Object#equals} or not.
*
* @param value the non-null value to check
* @return true if given {@code value} is already cached
* @throws NullPointerException if value is null
*/
public boolean containsValue(V value) {
Objects.requireNonNull(value);
expungeStaleEntries();
return reverseMap.containsKey(new LookupValue<>(value));
}
/**
* Returns the current number of cached entries that
* can decrease over time when keys/values are GC-ed.
*/
public int size() {
expungeStaleEntries();
return reverseMap.size();
}
private void expungeStaleEntries() {
CacheKey<K> cacheKey;
while ((cacheKey = (CacheKey<K>)refQueue.poll()) != null) {
cacheKey.expungeFrom(map, reverseMap);
}
}
/**
* A factory {@link Supplier} that implements the lazy synchronized
* construction of the value and installment of it into the cache.
*/
private final class Factory implements Supplier<V> {
private final K key;
private final P parameter;
private final Object subKey;
private final ConcurrentMap<Object, Supplier<V>> valuesMap;
Factory(K key, P parameter, Object subKey,
ConcurrentMap<Object, Supplier<V>> valuesMap) {
this.key = key;
this.parameter = parameter;
this.subKey = subKey;
this.valuesMap = valuesMap;
}
@Override
public synchronized V get() { // serialize access
//校验是否为同一个
Supplier<V> supplier = valuesMap.get(subKey);
if (supplier != this) {
//在我们等待的时候,可能某些值已经被替换或则删除,返回null让WeakCache.get()再次循环获取
return null;
}
//创建一个新值
V value = null;
try {
//调用valueFactory的applay方法生成一个新值
value = Objects.requireNonNull(valueFactory.apply(key, parameter));
} finally {
if (value == null) { //如果生成失败,从valuesMap中删除值
valuesMap.remove(subKey, this);
}
}
// the only path to reach here is with non-null value
assert value != null;
// wrap value with CacheValue (WeakReference)
CacheValue<V> cacheValue = new CacheValue<>(value);
//尝试更换我们cachevalue(这应该总是成功的)此时
if (valuesMap.replace(subKey, this, cacheValue)) {
// 放在reversemap
reverseMap.put(cacheValue, Boolean.TRUE);
} else {
throw new AssertionError("Should not reach here");
}
//成功取代当前工厂对象为一个新的CacheValue(包裹着我们的需要对象:代理类)
return value;
}
}
//Value接口
private interface Value<V> extends Supplier<V> {}
//值对象:包裹着我们的需要对象:代理类
private static final class LookupValue<V> implements Value<V> {
private final V value;
LookupValue(V value) {
this.value = value;
}
@Override
public V get() {
return value;
}
@Override
public int hashCode() {
return System.identityHashCode(value); // compare by identity
}
@Override
public boolean equals(Object obj) {
return obj == this ||
obj instanceof Value &&
this.value == ((Value<?>) obj).get(); // compare by identity
}
}
/**
* A {@link Value} that weakly references the referent.
*/
private static final class CacheValue<V>
extends WeakReference<V> implements Value<V>
{
private final int hash;
CacheValue(V value) {
super(value);
this.hash = System.identityHashCode(value); // compare by identity
}
@Override
public int hashCode() {
return hash;
}
@Override
public boolean equals(Object obj) {
V value;
return obj == this ||
obj instanceof Value &&
// cleared CacheValue is only equal to itself
(value = get()) != null &&
value == ((Value<?>) obj).get(); // compare by identity
}
}
private static final class CacheKey<K> extends WeakReference<K> {
// a replacement for null keys
private static final Object NULL_KEY = new Object();
static <K> Object valueOf(K key, ReferenceQueue<K> refQueue) {
return key == null
// null key means we can't weakly reference it,
// so we use a NULL_KEY singleton as cache key
? NULL_KEY
// non-null key requires wrapping with a WeakReference
: new CacheKey<>(key, refQueue);
}
private final int hash;
private CacheKey(K key, ReferenceQueue<K> refQueue) {
super(key, refQueue);
this.hash = System.identityHashCode(key); // compare by identity
}
@Override
public int hashCode() {
return hash;
}
@Override
public boolean equals(Object obj) {
K key;
return obj == this ||
obj != null &&
obj.getClass() == this.getClass() &&
// cleared CacheKey is only equal to itself
(key = this.get()) != null &&
// compare key by identity
key == ((CacheKey<K>) obj).get();
}
void expungeFrom(ConcurrentMap<?, ? extends ConcurrentMap<?, ?>> map,
ConcurrentMap<?, Boolean> reverseMap) {
// removing just by key is always safe here because after a CacheKey
// is cleared and enqueue-ed it is only equal to itself
// (see equals method)...
ConcurrentMap<?, ?> valuesMap = map.remove(this);
// remove also from reverseMap if needed
if (valuesMap != null) {
for (Object cacheValue : valuesMap.values()) {
reverseMap.remove(cacheValue);
}
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
Proxy实际生成的代理类
import dynamic.proxy.UserService;
import java.lang.reflect.*;
public final class $Proxy11 extends Proxy
implements UserService
{
// 构造方法,参数就是刚才传过来的MyInvocationHandler类的实例
public $Proxy11(InvocationHandler invocationhandler)
{
super(invocationhandler);
}
public final boolean equals(Object obj)
{
try
{
return ((Boolean)super.h.invoke(this, m1, new Object[] {
obj
})).booleanValue();
}
catch(Error _ex) { }
catch(Throwable throwable)
{
throw new UndeclaredThrowableException(throwable);
}
}
/**
* 这个方法是关键部分
*/
public final void add()
{
try
{
// 实际上就是调用MyInvocationHandler的public Object invoke(Object proxy, Method method, Object[] args)方法,第二个问题就解决了
super.h.invoke(this, m3, null);
return;
}
catch(Error _ex) { }
catch(Throwable throwable)
{
throw new UndeclaredThrowableException(throwable);
}
}
public final int hashCode()
{
try
{
return ((Integer)super.h.invoke(this, m0, null)).intValue();
}
catch(Error _ex) { }
catch(Throwable throwable)
{
throw new UndeclaredThrowableException(throwable);
}
}
public final String toString()
{
try
{
return (String)super.h.invoke(this, m2, null);
}
catch(Error _ex) { }
catch(Throwable throwable)
{
throw new UndeclaredThrowableException(throwable);
}
}
private static Method m1;
private static Method m3;
private static Method m0;
private static Method m2;
// 在静态代码块中获取了4个方法:Object中的equals方法、UserService中的add方法、Object中的hashCode方法、Object中toString方法
static
{
try
{
m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] {
Class.forName("java.lang.Object")
});
m3 = Class.forName("dynamic.proxy.UserService").getMethod("add", new Class[0]);
m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
}
catch(NoSuchMethodException nosuchmethodexception)
{
throw new NoSuchMethodError(nosuchmethodexception.getMessage());
}
catch(ClassNotFoundException classnotfoundexception)
{
throw new NoClassDefFoundError(classnotfoundexception.getMessage());
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
---------------------
JDK1.8 动态代理机制及源码解析的更多相关文章
- 给jdk写注释系列之jdk1.6容器(10)-Stack&Vector源码解析
前面我们已经接触过几种数据结构了,有数组.链表.Hash表.红黑树(二叉查询树),今天再来看另外一种数据结构:栈. 什么是栈呢,我就不找它具体的定义了,直接举个例子,栈就相当于一个很窄的木桶 ...
- grunt源码解析:整体运行机制&grunt-cli源码解析
前端的童鞋对grunt应该不陌生,前面也陆陆续续的写了几篇grunt入门的文章.本篇文章会更进一步,对grunt的源码进行分析.文章大体内容内容如下: grunt整体设计概览 grunt-cli源码分 ...
- Spark streaming技术内幕6 : Job动态生成原理与源码解析
原创文章,转载请注明:转载自 周岳飞博客(http://www.cnblogs.com/zhouyf/) Spark streaming 程序的运行过程是将DStream的操作转化成RDD的操作,S ...
- 6.Spark streaming技术内幕 : Job动态生成原理与源码解析
原创文章,转载请注明:转载自 周岳飞博客(http://www.cnblogs.com/zhouyf/) Spark streaming 程序的运行过程是将DStream的操作转化成RDD的操作, ...
- Python内存管理机制-《源码解析》
Python内存管理机制 Python 内存管理分层架构 /* An object allocator for Python. Here is an introduction to the layer ...
- Spark Shuffle机制详细源码解析
Shuffle过程主要分为Shuffle write和Shuffle read两个阶段,2.0版本之后hash shuffle被删除,只保留sort shuffle,下面结合代码分析: 1.Shuff ...
- Java 反射 设计模式 动态代理机制详解 [ 转载 ]
Java 反射 设计模式 动态代理机制详解 [ 转载 ] @author 亦山 原文链接:http://blog.csdn.net/luanlouis/article/details/24589193 ...
- Java的三种代理模式&完整源码分析
Java的三种代理模式&完整源码分析 参考资料: 博客园-Java的三种代理模式 简书-JDK动态代理-超详细源码分析 [博客园-WeakCache缓存的实现机制](https://www.c ...
- [源码解析] 从TimeoutException看Flink的心跳机制
[源码解析] 从TimeoutException看Flink的心跳机制 目录 [源码解析] 从TimeoutException看Flink的心跳机制 0x00 摘要 0x01 缘由 0x02 背景概念 ...
随机推荐
- (appium+python)UI自动化_08_unittest编写测试用例
前言 unittest是python自带的单元测试框架,类似于Junit(Java单元测试框架).支持自动化测试,可编写测试前置&后置条件,并且可批量运行测试用例并生成测试报告. 使用unit ...
- crontab自动执行任务,失败原因记录
服务器上使用crontab部署这两个每分钟自动执行的命令.首先,这两个命令是之前的人部署的,在我接手之前,就一直在了的.根据命令,实际上应该是做到每分钟都执行一次脚本.但是实际操作中,却发现,其实并没 ...
- SQLMap使用总结
支持模式:布尔/时间/报错/联合查询/堆查询 支持数据库:MySQL, Oracle, PostgreSQL, Microsoft SQL Server, Microsoft Access, IBM ...
- Python入门习题4.文本进度条
例4.1.设置一组文本进度条,使之运行效果如下: --------执行开始--------% 0 [->**********]%10 [*->*********]%20 [**->* ...
- python学习第二十天文件操作方法
字符有的存储在内存,有的存储在硬盘,文件也有增删改查的操作方法,open()方法,read()方法,readline()方法,close()文件关闭,write()写的方法,seek() 指针移动方法 ...
- harbar仓库的接口测试
一.接口测试命令 api接口文档:https://github.com/goharbor/harbor/blob/release-1.7.0/docs/swagger.yaml 1)查看所属项目的信息 ...
- K3 cloud中消耗性生物资产已郁闭达到可销售状态,要从消耗性生物资产转至库存商品,要如何结转?
处理方法: 先做出库单,然后做入库单,选择细目的时候出库单选择的是消耗性生物资产中的细目,如图所示: 然后入库的时候选择库存商品,如下图所示:
- ELK + Filebeat日志分析系统安装
之前搭建过elk,用于分析日志,无奈服务器资源不足,开了多个Logstash之后发现占用内存过高,于是现在改为Filebeat做日志收集,记录一下搭建过程和遇到问题的解决方案. 第一步 , 安装jdk ...
- ajax请求超时解决方案
设置timeout的时间,通过检测complete时status的值判断请求是否超时,如果超时执行响应的操作. var ajaxTimeoutTest=$.ajax({ url:'',//请求地址 t ...
- JavaScript深入之词法作用域和动态作用域(转载)
作用域 作用域是指程序源代码中定义变量的区域. 作用域规定了如何查找变量,也就是确定当前执行代码对变量的访问权限. JavaScript 采用词法作用域(lexical scoping),也就是静态作 ...