- public staticClass getProxyClass(ClassLoader loader,
- Class... interfaces)
- throws IllegalArgumentException
- {
- if(interfaces.length > 65535) {//因为在class文件中,一个类保存的接口数量是用2个字节来表示的,因此java中一个类最多可以实现65535个接口
- throw newIllegalArgumentException("interface limit exceeded");
- }
- ClassproxyClass =null;
- /* collect interface names to use as key for proxy class cache */
- String[] interfaceNames =new String[interfaces.length];
- // for detecting duplicatesSet> interfaceSet = newHashSet<>();
- //验证interfaces里的接口是否能被类加载器加载,是否是接口,是否有重复的
- for(inti = 0; i < interfaces.length; i++) {
- /*
- * Verify that the class loader resolves the name of this
- * interface to the same Class object.
- */
- String interfaceName = interfaces[i].getName();
- ClassinterfaceClass =null;
- try {
- interfaceClass = Class.forName(interfaceName,false, loader);
- } catch (ClassNotFoundException e) {
- }
- if(interfaceClass != interfaces[i]) {
- throw new IllegalArgumentException(
- interfaces[i] + " is not visible from class loader");
- }
- /*
- * Verify that the Class object actually represents an
- * interface.
- */
- if(!interfaceClass.isInterface()) {
- throw new IllegalArgumentException(
- interfaceClass.getName() + " is not an interface");
- }
- /*
- * Verify that this interface is not a duplicate.
- */
- if (interfaceSet.contains(interfaceClass)) {
- throw new IllegalArgumentException(
- "repeated interface: " + interfaceClass.getName());
- }
- interfaceSet.add(interfaceClass);
- interfaceNames[i] = interfaceName;
- }
- /*
- * Using string representations of the proxy interfaces as
- * keys in the proxy class cache (instead of their Class
- * objects) is sufficient because we require the proxy
- * interfaces to be resolvable by name through the supplied
- * class loader, and it has the advantage that using a string
- * representation of a class makes for an implicit weak
- * reference to the class.
- */
- List key = Arrays.asList(interfaceNames);//使用interfaces列表作为key缓存在cache里,也就是实现了相同interfaces的代理类只会创建加载一次
- /*
- * Find or create the proxy class cache for the class loader.
- */
- Map, Object> cache;
- synchronized (loaderToCache) {
- cache = loaderToCache.get(loader);
- if(cache ==null) {
- cache =newHashMap<>();
- loaderToCache.put(loader, cache);
- }
- /*
- * This mapping will remain valid for the duration of this
- * method, without further synchronization, because the mapping
- * will only be removed if the class loader becomes unreachable.
- */
- }
- /*
- * Look up the list of interfaces in the proxy class cache using
- * the key. This lookup will result in one of three possible
- * kinds of values:
- * null, if there is currently no proxy class for the list of
- * interfaces in the class loader,
- * the pendingGenerationMarker object, if a proxy class for the
- * list of interfaces is currently being generated,
- * or a weak reference to a Class object, if a proxy class for
- * the list of interfaces has already been generated.
- */
- //看看缓存里有没有,如果有就直接取出来然后return,否则判断根据pendingGenerationMarker判断是否有其它线程正在生成当前的代理类,如果有则cache.wait()等待,如果没有则创建。
- synchronized (cache) {
- /*
- * Note that we need not worry about reaping the cache for
- * entries with cleared weak references because if a proxy class
- * has been garbage collected, its class loader will have been
- * garbage collected as well, so the entire cache will be reaped
- * from the loaderToCache map.
- */
- do {
- Object value = cache.get(key);
- if(valueinstanceof Reference) {
- proxyClass = (Class) ((Reference) value).get();
- }
- if(proxyClass !=null) {
- // proxy class already generated: return it
- return proxyClass;
- } else if(value == pendingGenerationMarker) {
- // proxy class being generated: wait for it
- try {
- cache.wait();
- } catch (InterruptedException e) {
- /*
- * The class generation that we are waiting for should
- * take a small, bounded time, so we can safely ignore
- * thread interrupts here.
- */
- }
- continue;
- } else {
- /*
- * No proxy class for this list of interfaces has been
- * generated or is being generated, so we will go and
- * generate it now. Mark it as pending generation.
- */
- cache.put(key, pendingGenerationMarker);
- break;
- }
- } while(true);
- }
- //确认要生成的代理类所属的包,如果interfaces里所有接口都是public的,代理类所属包就是默认包;如果有interface不是public,那么所有不是public的interface必须在一个包里否则报错。
- try {
- String proxyPkg =null;// package to define proxy class in
- /*
- * 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(inti = 0; i < interfaces.length; i++) {
- intflags = interfaces[i].getModifiers();
- if(!Modifier.isPublic(flags)) {
- String name = interfaces[i].getName();
- intn = name.lastIndexOf('.');
- String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
- if(proxyPkg ==null) {
- proxyPkg = pkg;
- } else if(!pkg.equals(proxyPkg)) {
- throw new IllegalArgumentException(
- "non-public interfaces from different packages");
- }
- }
- }
- if(proxyPkg ==null) {// if no non-public proxy interfaces,proxyPkg = "";// use the unnamed package
- }
- {
- /*
- * Choose a name for the proxy class to generate.
- */
- long num;
- synchronized (nextUniqueNumberLock) {
- num = nextUniqueNumber++;
- }
- String proxyName = proxyPkg + proxyClassNamePrefix + num;//生成代理类的名字,proxyPkg是上面确定下来的代理类所在的包名,proxyClassNamePrefix是写死的字符串"$Proxy",num是一个全局唯一的long型数字,从0开始累积,每次生成新的代理类就+1,从这里也能看出生成的动态代理类的数量不能超过Long.maxValue
- /*
- * Verify that the class loader hasn't already
- * defined a class with the chosen name.
- */
- /*
- * Generate the specified proxy class.
- */
- byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
- proxyName, interfaces);//生成一个以proxyName为类名的,实现了Interfaces里所有接口的类的字节码
- try {
- proxyClass = 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());
- }
- }
- // add to set of all generated proxy classes, for isProxyClassproxyClasses.put(proxyClass,null);
- } finally {
- /*
- * We must clean up the "pending generation" state of the proxy
- * class cache entry somehow. If a proxy class was successfully
- * generated, store it in the cache (with a weak reference);
- * otherwise, remove the reserved entry. In all cases, notify
- * all waiters on reserved entries in this cache.
- */
- //创建成功,则将cache中该key的pendingGenerationMarker替换为实际的代理类的弱引用,否则也要清除pendingGenerationMarker标记;不管是否成功,都要执行cache.notifyAll(),让其它要创建相同代理类并且执行了cache.wait()的线程恢复执行。
来源: