forked from kangjianwei/LearningJDK
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Proxy.java
1398 lines (1235 loc) · 64.4 KB
/
Proxy.java
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
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.lang.reflect;
import java.io.Serializable;
import java.lang.module.ModuleDescriptor;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import jdk.internal.loader.AbstractClassLoaderValue;
import jdk.internal.loader.BootLoader;
import jdk.internal.loader.ClassLoaderValue;
import jdk.internal.misc.Unsafe;
import jdk.internal.misc.VM;
import jdk.internal.module.Modules;
import jdk.internal.reflect.CallerSensitive;
import jdk.internal.reflect.Reflection;
import sun.reflect.misc.ReflectUtil;
import sun.security.action.GetPropertyAction;
import sun.security.util.SecurityConstants;
import static java.lang.module.ModuleDescriptor.Modifier.SYNTHETIC;
/**
* {@code Proxy} provides static methods for creating objects that act like instances
* of interfaces but allow for customized method invocation.
* To create a proxy instance for some interface {@code Foo}:
* <pre>{@code
* InvocationHandler handler = new MyInvocationHandler(...);
* Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),
* new Class<?>[] { Foo.class },
* handler);
* }</pre>
*
* <p>
* A <em>proxy class</em> is a class created at runtime that implements a specified
* list of interfaces, known as <em>proxy interfaces</em>. A <em>proxy instance</em>
* is an instance of a proxy class.
*
* Each proxy instance has an associated <i>invocation handler</i>
* object, which implements the interface {@link InvocationHandler}.
* A method invocation on a proxy instance through one of its proxy
* interfaces will be dispatched to the {@link InvocationHandler#invoke
* invoke} method of the instance's invocation handler, passing the proxy
* instance, a {@code java.lang.reflect.Method} object identifying
* the method that was invoked, and an array of type {@code Object}
* containing the arguments. The invocation handler processes the
* encoded method invocation as appropriate and the result that it
* returns will be returned as the result of the method invocation on
* the proxy instance.
*
* <p>A proxy class has the following properties:
*
* <ul>
* <li>The unqualified name of a proxy class is unspecified. The space
* of class names that begin with the string {@code "$Proxy"}
* should be, however, reserved for proxy classes.
*
* <li>The package and module in which a proxy class is defined is specified
* <a href="#membership">below</a>.
*
* <li>A proxy class is <em>final and non-abstract</em>.
*
* <li>A proxy class extends {@code java.lang.reflect.Proxy}.
*
* <li>A proxy class implements exactly the interfaces specified at its
* creation, in the same order. Invoking {@link Class#getInterfaces() getInterfaces}
* on its {@code Class} object will return an array containing the same
* list of interfaces (in the order specified at its creation), invoking
* {@link Class#getMethods getMethods} on its {@code Class} object will return
* an array of {@code Method} objects that include all of the
* methods in those interfaces, and invoking {@code getMethod} will
* find methods in the proxy interfaces as would be expected.
*
* <li>The {@link java.security.ProtectionDomain} of a proxy class
* is the same as that of system classes loaded by the bootstrap class
* loader, such as {@code java.lang.Object}, because the code for a
* proxy class is generated by trusted system code. This protection
* domain will typically be granted {@code java.security.AllPermission}.
*
* <li>The {@link Proxy#isProxyClass Proxy.isProxyClass} method can be used
* to determine if a given class is a proxy class.
* </ul>
*
* <p>A proxy instance has the following properties:
*
* <ul>
* <li>Given a proxy instance {@code proxy} and one of the
* interfaces, {@code Foo}, implemented by its proxy class, the
* following expression will return true:
* <pre>
* {@code proxy instanceof Foo}
* </pre>
* and the following cast operation will succeed (rather than throwing
* a {@code ClassCastException}):
* <pre>
* {@code (Foo) proxy}
* </pre>
*
* <li>Each proxy instance has an associated invocation handler, the one
* that was passed to its constructor. The static
* {@link Proxy#getInvocationHandler Proxy.getInvocationHandler} method
* will return the invocation handler associated with the proxy instance
* passed as its argument.
*
* <li>An interface method invocation on a proxy instance will be
* encoded and dispatched to the invocation handler's {@link
* InvocationHandler#invoke invoke} method as described in the
* documentation for that method.
*
* <li>An invocation of the {@code hashCode},
* {@code equals}, or {@code toString} methods declared in
* {@code java.lang.Object} on a proxy instance will be encoded and
* dispatched to the invocation handler's {@code invoke} method in
* the same manner as interface method invocations are encoded and
* dispatched, as described above. The declaring class of the
* {@code Method} object passed to {@code invoke} will be
* {@code java.lang.Object}. Other public methods of a proxy
* instance inherited from {@code java.lang.Object} are not
* overridden by a proxy class, so invocations of those methods behave
* like they do for instances of {@code java.lang.Object}.
* </ul>
*
* <h3><a id="membership">Package and Module Membership of Proxy Class</a></h3>
*
* The package and module to which a proxy class belongs are chosen such that
* the accessibility of the proxy class is in line with the accessibility of
* the proxy interfaces. Specifically, the package and the module membership
* of a proxy class defined via the
* {@link Proxy#getProxyClass(ClassLoader, Class[])} or
* {@link Proxy#newProxyInstance(ClassLoader, Class[], InvocationHandler)}
* methods is specified as follows:
*
* <ol>
* <li>If all the proxy interfaces are in <em>exported</em> or <em>open</em>
* packages:
* <ol type="a">
* <li>if all the proxy interfaces are <em>public</em>, then the proxy class is
* <em>public</em> in a package exported by the
* {@linkplain ClassLoader#getUnnamedModule() unnamed module} of the specified
* loader. The name of the package is unspecified.</li>
*
* <li>if at least one of all the proxy interfaces is <em>non-public</em>, then
* the proxy class is <em>non-public</em> in the package and module of the
* non-public interfaces. All the non-public interfaces must be in the same
* package and module; otherwise, proxying them is
* <a href="#restrictions">not possible</a>.</li>
* </ol>
* </li>
* <li>If at least one proxy interface is in a package that is
* <em>non-exported</em> and <em>non-open</em>:
* <ol type="a">
* <li>if all the proxy interfaces are <em>public</em>, then the proxy class is
* <em>public</em> in a <em>non-exported</em>, <em>non-open</em> package of
* <a href="#dynamicmodule"><em>dynamic module</em>.</a>
* The names of the package and the module are unspecified.</li>
*
* <li>if at least one of all the proxy interfaces is <em>non-public</em>, then
* the proxy class is <em>non-public</em> in the package and module of the
* non-public interfaces. All the non-public interfaces must be in the same
* package and module; otherwise, proxying them is
* <a href="#restrictions">not possible</a>.</li>
* </ol>
* </li>
* </ol>
*
* <p>
* Note that if proxy interfaces with a mix of accessibilities -- for example,
* an exported public interface and a non-exported non-public interface -- are
* proxied by the same instance, then the proxy class's accessibility is
* governed by the least accessible proxy interface.
* <p>
* Note that it is possible for arbitrary code to obtain access to a proxy class
* in an open package with {@link AccessibleObject#setAccessible setAccessible},
* whereas a proxy class in a non-open package is never accessible to
* code outside the module of the proxy class.
*
* <p>
* Throughout this specification, a "non-exported package" refers to a package
* that is not exported to all modules, and a "non-open package" refers to
* a package that is not open to all modules. Specifically, these terms refer to
* a package that either is not exported/open by its containing module or is
* exported/open in a qualified fashion by its containing module.
*
* <h3><a id="dynamicmodule">Dynamic Modules</a></h3>
* <p>
* A dynamic module is a named module generated at runtime. A proxy class
* defined in a dynamic module is encapsulated and not accessible to any module.
* Calling {@link Constructor#newInstance(Object...)} on a proxy class in
* a dynamic module will throw {@code IllegalAccessException};
* {@code Proxy.newProxyInstance} method should be used instead.
*
* <p>
* A dynamic module can read the modules of all of the superinterfaces of a proxy
* class and the modules of the types referenced by all public method signatures
* of a proxy class. If a superinterface or a referenced type, say {@code T},
* is in a non-exported package, the {@linkplain Module module} of {@code T} is
* updated to export the package of {@code T} to the dynamic module.
*
* <h3>Methods Duplicated in Multiple Proxy Interfaces</h3>
*
* <p>When two or more proxy interfaces contain a method with
* the same name and parameter signature, the order of the proxy class's
* interfaces becomes significant. When such a <i>duplicate method</i>
* is invoked on a proxy instance, the {@code Method} object passed
* to the invocation handler will not necessarily be the one whose
* declaring class is assignable from the reference type of the interface
* that the proxy's method was invoked through. This limitation exists
* because the corresponding method implementation in the generated proxy
* class cannot determine which interface it was invoked through.
* Therefore, when a duplicate method is invoked on a proxy instance,
* the {@code Method} object for the method in the foremost interface
* that contains the method (either directly or inherited through a
* superinterface) in the proxy class's list of interfaces is passed to
* the invocation handler's {@code invoke} method, regardless of the
* reference type through which the method invocation occurred.
*
* <p>If a proxy interface contains a method with the same name and
* parameter signature as the {@code hashCode}, {@code equals},
* or {@code toString} methods of {@code java.lang.Object},
* when such a method is invoked on a proxy instance, the
* {@code Method} object passed to the invocation handler will have
* {@code java.lang.Object} as its declaring class. In other words,
* the public, non-final methods of {@code java.lang.Object}
* logically precede all of the proxy interfaces for the determination of
* which {@code Method} object to pass to the invocation handler.
*
* <p>Note also that when a duplicate method is dispatched to an
* invocation handler, the {@code invoke} method may only throw
* checked exception types that are assignable to one of the exception
* types in the {@code throws} clause of the method in <i>all</i> of
* the proxy interfaces that it can be invoked through. If the
* {@code invoke} method throws a checked exception that is not
* assignable to any of the exception types declared by the method in one
* of the proxy interfaces that it can be invoked through, then an
* unchecked {@code UndeclaredThrowableException} will be thrown by
* the invocation on the proxy instance. This restriction means that not
* all of the exception types returned by invoking
* {@code getExceptionTypes} on the {@code Method} object
* passed to the {@code invoke} method can necessarily be thrown
* successfully by the {@code invoke} method.
*
* @author Peter Jones
* @revised 9
* @spec JPMS
* @see InvocationHandler
* @since 1.3
*/
/*
* JDK默认的动态代理
*
* Proxy作为所有代理类的父类,用来生成代理对象
*
* 【示例】
*
* 假设有代理接口:
* package con.kang;
*
* interface Subject {
* void request(); // 目标方法
* }
*
* 则需要构造一个被代理类:
* public class SubjectImpl interface Subject {
* // 被代理方法
* void request() {
* }
* }
*
* 实现回调引用:
* public class SubjectHandler interface InvocationHandler {
* private Subject target; // 被代理对象
*
* public SubjectHandler(Subject target) {
* this.target = target;
* }
*
* // 代理回调方法
* public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
* // 代理前的操作...
*
* method.invoke(target);
*
* // 代理后的操作...
*
* return null;
* }
* }
*
* 或者,将以上两步合并(不推荐)
* public class SubjectImpl interface Subject, InvocationHandler {
* private Subject target; // 被代理对象
*
* public SubjectHandler(Subject target) {
* this.target = target;
* }
*
* // 被代理方法
* void request() {
* }
*
* // 代理回调方法
* public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
* // 代理前的操作...
*
* method.invoke(target); // 间接调用被代理方法
*
* // 代理后的操作...
*
* return null;
* }
* }
*
* 系统生成的代理类为(除去了无关枝节):
* final class $Proxy0 extends Proxy implements Subject {
* private static Method method; // 被代理方法
*
* static {
* method = Class.forName("com.kang.Subject").getMethod("request");
* }
*
* public $Proxy0(InvocationHandler h) {
* super(h);
* }
*
* // 代理方法
* public final void request() {
* // 通过代理回调方法,来回调被代理方法
* super.h.invoke(this, method, (Object[])null);
* }
* }
*
* 随后,可以通过Proxy.newProxyInstance(...)获取代理类对象,并调用代理方法
*
* 生成代理类时,如果开启"jdk.proxy.ProxyGenerator.saveGeneratedFiles"属性,则可以得到代理类字节码文件,参见ProxyGenerator。
*/
public class Proxy implements Serializable {
private static final long serialVersionUID = -2222568056686623797L;
/**
* the invocation handler for this proxy instance.
*
* @serial
*/
protected InvocationHandler h; // 回调引用,在代理方法中通过此回调引用来间接调用被代理方法
/** parameter types of a proxy class constructor */
// 代理类构造器参数(固定)
private static final Class<?>[] constructorParams = {InvocationHandler.class};
/**
* a cache of proxy constructors with {@link Constructor#setAccessible(boolean) accessible} flag already set
*/
// root-clv,此处主要用来构造sub-clv
private static final ClassLoaderValue<Constructor<?>> proxyCache = new ClassLoaderValue<>();
private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
// 代理接口都是public时,代理类需要统一使用该包名
private static final String PROXY_PACKAGE_PREFIX = ReflectUtil.PROXY_PACKAGE;
/*▼ 构造器 ████████████████████████████████████████████████████████████████████████████████┓ */
/**
* Prohibits instantiation.
*/
private Proxy() {
}
/**
* Constructs a new {@code Proxy} instance from a subclass
* (typically, a dynamic proxy class) with the specified value
* for its invocation handler.
*
* @param h the invocation handler for this proxy instance
*
* @throws NullPointerException if the given invocation handler, {@code h},
* is {@code null}.
*/
// 由代理类(Proxy的子类)调用:给回调引用赋值,以便找到被代理对象
protected Proxy(InvocationHandler h) {
Objects.requireNonNull(h);
this.h = h;
}
/*▲ 构造器 ████████████████████████████████████████████████████████████████████████████████┛ */
/*▼ 工厂方法 ████████████████████████████████████████████████████████████████████████████████┓ */
/**
* Returns a proxy instance for the specified interfaces
* that dispatches method invocations to the specified invocation
* handler.
* <p>
* <a id="restrictions">{@code IllegalArgumentException} will be thrown
* if any of the following restrictions is violated:</a>
* <ul>
* <li>All of {@code Class} objects in the given {@code interfaces} array
* must represent interfaces, not classes or primitive types.
*
* <li>No two elements in the {@code interfaces} array may
* refer to identical {@code Class} objects.
*
* <li>All of the interface types must be visible by name through the
* specified class loader. In other words, for class loader
* {@code cl} and every interface {@code i}, the following
* expression must be true:<p>
* {@code Class.forName(i.getName(), false, cl) == i}
*
* <li>All of the types referenced by all
* public method signatures of the specified interfaces
* and those inherited by their superinterfaces
* must be visible by name through the specified class loader.
*
* <li>All non-public interfaces must be in the same package
* and module, defined by the specified class loader and
* the module of the non-public interfaces can access all of
* the interface types; otherwise, it would not be possible for
* the proxy class to implement all of the interfaces,
* regardless of what package it is defined in.
*
* <li>For any set of member methods of the specified interfaces
* that have the same signature:
* <ul>
* <li>If the return type of any of the methods is a primitive
* type or void, then all of the methods must have that same
* return type.
* <li>Otherwise, one of the methods must have a return type that
* is assignable to all of the return types of the rest of the
* methods.
* </ul>
*
* <li>The resulting proxy class must not exceed any limits imposed
* on classes by the virtual machine. For example, the VM may limit
* the number of interfaces that a class may implement to 65535; in
* that case, the size of the {@code interfaces} array must not
* exceed 65535.
* </ul>
*
* <p>Note that the order of the specified proxy interfaces is
* significant: two requests for a proxy class with the same combination
* of interfaces but in a different order will result in two distinct
* proxy classes.
*
* @param loader the class loader to define the proxy class
* @param interfaces the list of interfaces for the proxy class
* to implement
* @param h the invocation handler to dispatch method invocations to
*
* @return a proxy instance with the specified invocation handler of a
* proxy class that is defined by the specified class loader
* and that implements the specified interfaces
*
* @throws IllegalArgumentException if any of the <a href="#restrictions">
* restrictions</a> on the parameters are violated
* @throws SecurityException if a security manager, <em>s</em>, is present
* and any of the following conditions is met:
* <ul>
* <li> the given {@code loader} is {@code null} and
* the caller's class loader is not {@code null} and the
* invocation of {@link SecurityManager#checkPermission
* s.checkPermission} with
* {@code RuntimePermission("getClassLoader")} permission
* denies access;</li>
* <li> for each proxy interface, {@code intf},
* the caller's class loader is not the same as or an
* ancestor of the class loader for {@code intf} and
* invocation of {@link SecurityManager#checkPackageAccess
* s.checkPackageAccess()} denies access to {@code intf};</li>
* <li> any of the given proxy interfaces is non-public and the
* caller class is not in the same {@linkplain Package runtime package}
* as the non-public interface and the invocation of
* {@link SecurityManager#checkPermission s.checkPermission} with
* {@code ReflectPermission("newProxyInPackage.{package name}")}
* permission denies access.</li>
* </ul>
* @throws NullPointerException if the {@code interfaces} array
* argument or any of its elements are {@code null}, or
* if the invocation handler, {@code h}, is
* {@code null}
* @revised 9
* @spec JPMS
* @see <a href="#membership">Package and Module Membership of Proxy Class</a>
*/
/*
* 工厂方法:生成动态代理对象
*
* loader :用于加载代理对象的类加载器,一般与被代理对象的类加载器一致
* interfaces:代理接口
* h :回调引用,可以在回调引用的内部持有被代理对象的引用,或者,回调引用本身也是被代理对象
*/
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) {
Objects.requireNonNull(h);
// 如果存在安全管理器,返回newProxyInstance()方法的调用者所处的类
final Class<?> caller = System.getSecurityManager() == null ? null : Reflection.getCallerClass();
/* Look up or generate the designated proxy class and its constructor. */
// 获取代理类的专用构造器:该构造器的形参必须为InvocationHandler类型
Constructor<?> cons = getProxyConstructor(caller, loader, interfaces);
// 生成动态代理对象并返回
return newProxyInstance(caller, cons, h);
}
/*▲ 工厂方法 ████████████████████████████████████████████████████████████████████████████████┛ */
/**
* Returns the invocation handler for the specified proxy instance.
*
* @param proxy the proxy instance to return the invocation handler for
*
* @return the invocation handler for the proxy instance
*
* @throws IllegalArgumentException if the argument is not a
* proxy instance
* @throws SecurityException if a security manager, <em>s</em>, is present
* and the caller's class loader is not the same as or an
* ancestor of the class loader for the invocation handler
* and invocation of {@link SecurityManager#checkPackageAccess
* s.checkPackageAccess()} denies access to the invocation
* handler's class.
*/
// 返回代理类内部的回调处理器
@CallerSensitive
public static InvocationHandler getInvocationHandler(Object proxy) throws IllegalArgumentException {
/* Verify that the object is actually a proxy instance */
// 如果proxy不是代理类,抛异常
if(!isProxyClass(proxy.getClass())) {
throw new IllegalArgumentException("not a proxy instance");
}
final InvocationHandler ih = ((Proxy) proxy).h;
// 如果不存在安全管理器,直接返回
if(System.getSecurityManager() == null) {
return ih;
}
// 获取getInvocationHandler()的调用者所在的类
Class<?> caller = Reflection.getCallerClass();
// 获取代理类
Class<?> ihClass = ih.getClass();
// 判断在caller访问ihClass时,是否需要检查包访问权限
if(ReflectUtil.needsPackageAccessCheck(caller.getClassLoader(), ihClass.getClassLoader())) {
// 检查当前线程对ihClass所在的包的访问权限
ReflectUtil.checkPackageAccess(ihClass);
}
return ih;
}
/**
* Returns true if the given class is a proxy class.
*
* @param cl the class to test
*
* @return {@code true} if the class is a proxy class and
* {@code false} otherwise
*
* @throws NullPointerException if {@code cl} is {@code null}
* @implNote The reliability of this method is important for the ability
* to use it to make security decisions, so its implementation should
* not just test if the class in question extends {@code Proxy}.
* @revised 9
* @spec JPMS
*/
// 判断proxyClass是否为代理类
public static boolean isProxyClass(Class<?> proxyClass) {
return Proxy.class.isAssignableFrom(proxyClass) // 要求proxyClass是Proxy类型
&& ProxyBuilder.isProxyClass(proxyClass); // 要求proxyClass位于相应类加载器的代理类缓存中
}
/**
* Returns the {@code java.lang.Class} object for a proxy class
* given a class loader and an array of interfaces. The proxy class
* will be defined by the specified class loader and will implement
* all of the supplied interfaces. If any of the given interfaces
* is non-public, the proxy class will be non-public. If a proxy class
* for the same permutation of interfaces has already been defined by the
* class loader, then the existing proxy class will be returned; otherwise,
* a proxy class for those interfaces will be generated dynamically
* and defined by the class loader.
*
* @param loader the class loader to define the proxy class
* @param interfaces the list of interfaces for the proxy class
* to implement
*
* @return a proxy class that is defined in the specified class loader
* and that implements the specified interfaces
*
* @throws IllegalArgumentException if any of the <a href="#restrictions">
* restrictions</a> on the parameters are violated
* @throws SecurityException if a security manager, <em>s</em>, is present
* and any of the following conditions is met:
* <ul>
* <li> the given {@code loader} is {@code null} and
* the caller's class loader is not {@code null} and the
* invocation of {@link SecurityManager#checkPermission
* s.checkPermission} with
* {@code RuntimePermission("getClassLoader")} permission
* denies access.</li>
* <li> for each proxy interface, {@code intf},
* the caller's class loader is not the same as or an
* ancestor of the class loader for {@code intf} and
* invocation of {@link SecurityManager#checkPackageAccess
* s.checkPackageAccess()} denies access to {@code intf}.</li>
* </ul>
* @throws NullPointerException if the {@code interfaces} array
* argument or any of its elements are {@code null}
* @revised 9
* @spec JPMS
* @see <a href="#membership">Package and Module Membership of Proxy Class</a>
* @deprecated Proxy classes generated in a named module are encapsulated
* and not accessible to code outside its module.
* {@link Constructor#newInstance(Object...) Constructor.newInstance}
* will throw {@code IllegalAccessException} when it is called on
* an inaccessible proxy class.
* Use {@link #newProxyInstance(ClassLoader, Class[], InvocationHandler)}
* to create a proxy instance instead.
*/
// 返回代理类的类对象;该方法已过时,需要使用支持模块语义的ProxyBuilder#defineProxyClass()
@Deprecated
@CallerSensitive
public static Class<?> getProxyClass(ClassLoader loader, Class<?>... interfaces) throws IllegalArgumentException {
Class<?> caller = System.getSecurityManager() == null ? null : Reflection.getCallerClass();
// 返回代理类的专用构造器:该构造器的形参必须为InvocationHandler类型
Constructor<?> constructor = getProxyConstructor(caller, loader, interfaces);
return constructor.getDeclaringClass(); // 返回构造器所在的类
}
/**
* Returns the {@code Constructor} object of a proxy class that takes a
* single argument of type {@link InvocationHandler}, given a class loader
* and an array of interfaces. The returned constructor will have the
* {@link Constructor#setAccessible(boolean) accessible} flag already set.
*
* @param caller passed from a public-facing @CallerSensitive method if
* SecurityManager is set or {@code null} if there's no
* SecurityManager
* @param loader the class loader to define the proxy class
* @param interfaces the list of interfaces for the proxy class
* to implement
*
* @return a Constructor of the proxy class taking single
* {@code InvocationHandler} parameter
*/
// 返回代理类的专用构造器:该构造器的形参必须为InvocationHandler类型
private static Constructor<?> getProxyConstructor(Class<?> caller, ClassLoader loader, Class<?>... interfaces) {
// 如果只有一个被代理接口
if(interfaces.length == 1) {
Class<?> intf = interfaces[0];
if(caller != null) {
// 检查caller对代理接口interfaces的访问权限,以及loader为null时检查getClassLoader权限
checkProxyAccess(caller, loader, intf);
}
// 构造一个包含代理接口的sub-clv
AbstractClassLoaderValue<ClassLoaderValue<Constructor<?>>, Constructor<?>>.Sub<? extends Class<?>> subCLV = proxyCache.sub(intf);
// 返回subCLV在loader中的类加载器局部缓存中映射的代理类构造器,如果不存在,则计算出新的代理类构造器并缓存起来
return subCLV.computeIfAbsent(loader, (cl, clv) -> new ProxyBuilder(cl, clv.key()).build());
// 如果存在多个被代理接口
} else {
// interfaces cloned
final Class<?>[] intfsArray = interfaces.clone();
if(caller != null) {
// 检查caller对代理接口interfaces的访问权限,以及loader为null时检查getClassLoader权限
checkProxyAccess(caller, loader, intfsArray);
}
final List<Class<?>> intfs = Arrays.asList(intfsArray);
// 构造一个包含代理接口的sub-clv
AbstractClassLoaderValue<ClassLoaderValue<Constructor<?>>, Constructor<?>>.Sub<List<Class<?>>> subCLV = proxyCache.sub(intfs);
// 返回subCLV在loader中的类加载器局部缓存中映射的代理类构造器,如果不存在,则计算出新的代理类构造器并缓存起来
return subCLV.computeIfAbsent(loader, (cl, clv) -> new ProxyBuilder(cl, clv.key()).build());
}
}
// 生成动态代理对象。如果没有SecurityManager,caller为null
private static Object newProxyInstance(Class<?> caller, Constructor<?> cons, InvocationHandler h) {
/*
* Invoke its constructor with the designated invocation handler.
*/
try {
if(caller != null) {
// 判断代理对象所在的类是否可以访问代理类(如果不能访问则无法调用构造器)
checkNewProxyPermission(caller, cons.getDeclaringClass());
}
return cons.newInstance(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);
}
}
}
/**
* Returns the class loader for the given module.
*/
// 返回加载指定模块的类加载器
private static ClassLoader getLoader(Module module) {
PrivilegedAction<ClassLoader> pa = () -> module.getClassLoader();
return AccessController.doPrivileged(pa);
}
/**
* Check permissions required to create a Proxy class.
*
* To define a proxy class, it performs the access checks as in
* Class.forName (VM will invoke ClassLoader.checkPackageAccess):
* 1. "getClassLoader" permission check if loader == null
* 2. checkPackageAccess on the interfaces it implements
*
* To get a constructor and new instance of a proxy class, it performs
* the package access check on the interfaces it implements
* as in Class.getConstructor.
*
* If an interface is non-public, the proxy class must be defined by
* the defining loader of the interface. If the caller's class loader
* is not the same as the defining loader of the interface, the VM
* will throw IllegalAccessError when the generated proxy class is
* being defined.
*/
// 检查caller对代理接口interfaces的访问权限,以及loader为null时检查getClassLoader权限
private static void checkProxyAccess(Class<?> caller, ClassLoader loader, Class<?>... interfaces) {
SecurityManager sm = System.getSecurityManager();
if(sm == null) {
return;
}
ClassLoader ccl = caller.getClassLoader();
if(loader == null && ccl != null) {
sm.checkPermission(SecurityConstants.GET_CLASSLOADER_PERMISSION);
}
// 检查ccl(加载的类)对代理接口interfaces的访问权限
ReflectUtil.checkProxyPackageAccess(ccl, interfaces);
}
// 判断caller是否可以访问proxyClass
private static void checkNewProxyPermission(Class<?> caller, Class<?> proxyClass) {
SecurityManager sm = System.getSecurityManager();
if(sm == null) {
return;
}
// 判断proxyClass是否为实现了非public代理接口的代理类
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
String callerPkg = caller.getPackageName();
String pkg = proxyClass.getPackageName();
if(ccl != pcl || !pkg.equals(callerPkg)) {
sm.checkPermission(new ReflectPermission("newProxyInPackage." + pkg));
}
}
}
/**
* Builder for a proxy class.
*
* If the module is not specified in this ProxyBuilder constructor,
* it will map from the given loader and interfaces to the module
* in which the proxy class will be defined.
*/
// 代理类构建器
private static final class ProxyBuilder {
private static final String DEBUG = GetPropertyAction.privilegedGetProperty("jdk.proxy.debug", "");
private static final Unsafe UNSAFE = Unsafe.getUnsafe();
private static final AtomicInteger counter = new AtomicInteger(); // 动态代理所在模块/包的名称编号
/* next number to use for generation of unique proxy class names */
private static final AtomicLong nextUniqueNumber = new AtomicLong(); // 代理类名称编号
// prefix for all proxy class names
private static final String proxyClassNamePrefix = "$Proxy"; // 动态代理类名称前缀
private final List<Class<?>> interfaces; // 代理接口
private final Module module; // 动态代理类所在模块
/*
* 动态代理模块CLV,由所有代理类构建器对象共享
*
* 该CLV映射了一个动态代理模块,这个映射存储在加载该动态代理模块的类加载器的类加载器局部缓存中
*/
private static final ClassLoaderValue<Module> dynProxyModulesCLV = new ClassLoaderValue<>();
/*
* 代理类CLV的root-clv,由所有代理类构建器对象共享
*
* 可以借此root-clv创建一系列子级sub-clv,这些sub-clv内部存储了可由对应类加载器加载的代理类,
* 而对于sub-clv作为类加载器局部缓存的key这个功能来说,sub-clv只是简单地映射了一个Boolean.TRUE值。
*/
private static final ClassLoaderValue<Boolean> reverseProxyCacheCLV = new ClassLoaderValue<>(); // a reverse cache of defined proxy classes
ProxyBuilder(ClassLoader loader, Class<?> intf) {
this(loader, Collections.singletonList(intf));
}
ProxyBuilder(ClassLoader loader, List<Class<?>> interfaces) {
// 确保模块化系统已经初始化完成
if(!VM.isModuleSystemInited()) {
throw new InternalError("Proxy is not supported until module system is fully initialized");
}
// 代理接口数量不能超过65535
if(interfaces.size()>65535) {
throw new IllegalArgumentException("interface limit exceeded: " + interfaces.size());
}
// 获取所有代理接口中所有非静态目标方法需要用到类型
Set<Class<?>> refTypes = referencedTypes(loader, interfaces);
/* IAE if violates any restrictions specified in newProxyInstance */
// 确保类加载器loader可以完成对代理类的加载
validateProxyInterfaces(loader, interfaces, refTypes);
// 代理接口
this.interfaces = interfaces;
// (构造并)返回动态代理类所在模块
this.module = mapToModule(loader, interfaces, refTypes);
assert getLoader(module) == loader;
}
/**
* Generate a proxy class and return its proxy Constructor with
* accessible flag already set. If the target module does not have access
* to any interface types, IllegalAccessError will be thrown by the VM
* at defineClass time.
*
* Must call the checkProxyAccess method to perform permission checks
* before calling this.
*/
// 返回代理类的专用构造器:该构造器的形参必须为InvocationHandler类型
Constructor<?> build() {
// 生成代理类的类对象;module是代理类所在模块,interfaces是代理接口
Class<?> proxyClass = defineProxyClass(module, interfaces);
final Constructor<?> cons;
try {
// 获取代理类的构造器,该方法的形参必须为InvocationHandler类型
cons = proxyClass.getConstructor(constructorParams);
} catch(NoSuchMethodException e) {
throw new InternalError(e.toString(), e);
}
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
// 设置可访问性
cons.setAccessible(true);
return null;
}
});
return cons;
}
// 生成代理类的类对象;module是代理类所在模块,interfaces是代理接口
private static Class<?> defineProxyClass(Module module, List<Class<?>> interfaces) {
// 代理类所在的包
String proxyPkg = null; // package to define proxy class in
// 代理类访问接口
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.
*/
// 遍历代理接口,如果存在非public接口,需要对proxyPkg和accessFlags做出修正
for(Class<?> intf : interfaces) {
// 获取代理接口修饰符
int flags = intf.getModifiers();
// 如果存在非public代理接口
if(!Modifier.isPublic(flags)) {
// 代理类仅需要添加final修饰符
accessFlags = Modifier.FINAL; // non-public, final
// 代理接口所在的包
String pkg = intf.getPackageName();
// 如果当前代理接口是非public的,则代理类所在的包应当与代理接口所在的包一致
if(proxyPkg == null) {
proxyPkg = pkg;
} else if(!pkg.equals(proxyPkg)) {
throw new IllegalArgumentException("non-public interfaces from different packages");
}
}
}
// proxyPkg为null意味着代理接口都是是public的,此时使用统一的包名:"com.sun.proxy"
if(proxyPkg == null) {
// all proxy interfaces are public
proxyPkg = module.isNamed() ? PROXY_PACKAGE_PREFIX + "." + module.getName() // 如果代理类所在模块是命名模块,使用形如com.sun.proxy.jdk.proxy1这样的包名
: PROXY_PACKAGE_PREFIX; // 如果代理类所在模块是非命名模块,直接使用"com.sun.proxy"做包名
} else if(proxyPkg.isEmpty() && module.isNamed()) {
throw new IllegalArgumentException("Unnamed package cannot be added to " + module);
}
// 如果代理类所在模块是命名模块
if(module.isNamed()) {
// 需要确保代理类所在的包在该命名模块下辖的包中
if(!module.getDescriptor().packages().contains(proxyPkg)) {
throw new InternalError(proxyPkg + " not exist in " + module.getName());
}
}
/*
* Choose a name for the proxy class to generate.
*/
// 代理类的类名
long num = nextUniqueNumber.getAndIncrement();
String proxyName = proxyPkg.isEmpty() ? proxyClassNamePrefix + num // 形如"$Proxy0"
: proxyPkg + "." + proxyClassNamePrefix + num;
// 获取加载指定模块的类加载器
ClassLoader loader = getLoader(module);
trace(proxyName, module, loader, interfaces);
/* Generate the specified proxy class. */
// 动态生成代理类的字节码流
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces.toArray(EMPTY_CLASS_ARRAY), accessFlags);
try {
// 生成代理类的类对象
Class<?> proxyClass = UNSAFE.defineClass(proxyName, proxyClassFile, 0, proxyClassFile.length, loader, null);
// 构造一个包含指定代理类的类对象的sub-clv
AbstractClassLoaderValue<ClassLoaderValue<Boolean>, Boolean>.Sub<? extends Class<?>> subCLV = reverseProxyCacheCLV.sub(proxyClass);
// 向loader的类加载器局部缓存中存入一个subCLV对象到Boolean.TRUE的映射,并返回旧(目标)值,不允许覆盖