- 针对于方法调用动态分派的过程,虚拟机会在类的方法区建立一个虚方法表的数据结构(virtual method table)
- 针对于invokeinterface指令来说,虚拟机会建立一个叫做接口方法表的数据结构(interface method table)
- 虚方法表中的每一个方法都被描述出来一个方法调用的入口地址,如果子类没有重写(没有从父类继承的一些方法),子类中的虚方法表会直接指向父类(对象)当中的方法入口地址(如Object中的n多个方法子类没有重写)。对于子类重写的一些方法(相同方法描述符),他们的索引一样(子类找完找父类特定索引当中的位置,提高了查找的效率)。
- 现代JVM在执行JAVA代码都会结合两种执行:编译执行(通过即时编译器将字节码转成本地机器码来执行,会根据代码热点来生成相应的本地机器码)和解释执行(解释器读取字节码,遇到相应指令就执行指令)
- 基于栈的指令集与基于寄存器的指令集之间的关系:
1JVM执行指令时所采取的方式是基于栈的指令集
2基于栈的指令集主要的操作有入栈和出栈两种
3基于栈的指令集的优势在于它可以在不同平台之间移植,而基于寄存器的指令集是与硬件架构紧密关联的,无法做到可移植
4基于栈的指令集的缺点在于完成相同的操作,指令数量通常要比基于寄存器的指令集数量多;
5基于栈的指令集是在内存中完成操作的,而基于寄存器的指令集是直接由CPU来执行的,它是在高速缓冲区中进行执行的,速度要 比基于栈的指令集快的多。 - 通过字节码理解动态代理实现机制:
1)subject接口
2)实现subject接口的realSubject类
3)实现InvocationHandler接口的代理类DanamicSubject
4)主方法 -
public interface Subject { void request(); } public class RealSubject implements Subject { public void request(){ System.out.println("From real subject"); } } public class DanamicSubject implements InvocationHandler { private Object object; public DanamicSubject(Object object) { this.object = object; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Method before" + method); method.invoke(object,args); System.out.println("After calling" + method); return null; } }
创建一个代理对象
-
public class TestProxyByte { public static void main(String[] args) { System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles","true"); RealSubject real = new RealSubject(); // InvocationHandler invo = new DanamicSubject(real); Subject ds = (Subject) Proxy.newProxyInstance(real.getClass().getClassLoader(), real.getClass().getInterfaces(), new DanamicSubject(real)); // 调用Proxy类的newProxyInstance静态方法实际上: // 內含兩個操作:1动态生成代理类本身2创建所生成的代理类的实例(对象) ds.request(); System.out.println(ds.getClass()); } } 结果: Method beforepublic abstract void TestProxyByteCode.Subject.request() From real subject After callingpublic abstract void TestProxyByteCode.Subject.request() class com.sun.proxy.$Proxy0
- 主方法中可以通过设置 : sun.misc.ProxyGenerator.saveGeneratedFiles 配置文件的属性为true来保存 生成的动态代理类的.class字节码文件;生成的代理类的名称为$Proxy0.class
- 可以在idea中打开生成的文件(显示字节码的反编译结果):
1)动态代理中重写生成了Object类的equals,toString,hashCode方法,而Object类中的其他方法没有被生成。
2)实现了给定接口中的方法,其中都会调用super.h.invoke....的返回值(返回一个代理对象),super即Proxy类,h为InvocationHandler(由主程序传入的是DanamicSubject);即代理方法都会去调用InvocationHandler的invoke()方法,因此我们需要重写InvocationHandler的invoke()方法。public final class $Proxy0 extends Proxy implements Subject { private static Method m1; private static Method m2; private static Method m3; private static Method m0; public $Proxy0(InvocationHandler var1) throws { super(var1); } public final boolean equals(Object var1) throws { try { return (Boolean)super.h.invoke(this, m1, new Object[]{var1}); } catch (RuntimeException | Error var3) { throw var3; } catch (Throwable var4) { throw new UndeclaredThrowableException(var4); } } public final String toString() throws { try { return (String)super.h.invoke(this, m2, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } public final void request() throws { try { super.h.invoke(this, m3, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } public final int hashCode() throws { try { return (Integer)super.h.invoke(this, m0, (Object[])null); } catch (RuntimeException | Error var2) { throw var2; } catch (Throwable var3) { throw new UndeclaredThrowableException(var3); } } static { try { m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object")); m2 = Class.forName("java.lang.Object").getMethod("toString"); m3 = Class.forName("TestProxyByteCode.Subject").getMethod("request"); m0 = Class.forName("java.lang.Object").getMethod("hashCode"); } catch (NoSuchMethodException var2) { throw new NoSuchMethodError(var2.getMessage()); } catch (ClassNotFoundException var3) { throw new NoClassDefFoundError(var3.getMessage()); } } }
- 调用Proxy类的newProxyInstance静态方法创建代理对象源码解析:
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); } /* * Look up or generate the designated proxy class. */ Class<?> cl = getProxyClass0(loader, intfs); /* * Invoke its constructor with the designated invocation handler. */ try { if (sm != null) { checkNewProxyPermission(Reflection.getCallerClass(), cl); } final Constructor<?> cons = cl.getConstructor(constructorParams); final InvocationHandler ih = h; if (!Modifier.isPublic(cl.getModifiers())) { AccessController.doPrivileged(new PrivilegedAction<Void>() { public Void run() { cons.setAccessible(true); return null; } }); } //Constructor.newInstance(.....) 可以根据传入的参数,调用相应的构造函数 //此处为代理类的构造函数,所有代理类都继承自Proxy, 因此这里会调用Proxy的构造器 //将InvocationHandler引用传入 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); } }
其中getProxyClass0方法生成了代理类的类对象
-
通过类加载器和接口集合去缓存里面获取(待补充其源码分析),如果能找到代理类就直接返回;否则就会调用ProxyClassFactory这个工厂去生成一个代理类/** * Generate a proxy class. Must call the checkProxyAccess method * to perform permission checks before calling this. */ private static Class<?> getProxyClass0(ClassLoader loader, Class<?>... interfaces) { if (interfaces.length > 65535) { throw new IllegalArgumentException("interface limit exceeded"); } // If the proxy class defined by the given loader implementing // the given interfaces exists, this will simply return the cached copy; // otherwise, it will create the proxy class via the ProxyClassFactory return proxyClassCache.get(loader, interfaces); }
- ProxyClassFactory源码分析:
//* A factory function that generates, defines and returns the proxy class given // the ClassLoader and array of interfaces. // private static final class ProxyClassFactory implements BiFunction<ClassLoader, Class<?>[], Class<?>> { // prefix for all proxy class names private static final String proxyClassNamePrefix = "$Proxy"; // next number to use for generation of unique proxy class names 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) { /* * Verify that the class loader resolves the name of this * interface to the same Class object. */ Class<?> interfaceClass = null; try { interfaceClass = Class.forName(intf.getName(), false, loader); } catch (ClassNotFoundException e) { } if (interfaceClass != intf) { throw new IllegalArgumentException( intf + " 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.put(interfaceClass, Boolean.TRUE) != null) { throw new IllegalArgumentException( "repeated interface: " + interfaceClass.getName()); } } 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. */ for (Class<?> intf : interfaces) { int flags = intf.getModifiers(); if (!Modifier.isPublic(flags)) { accessFlags = Modifier.FINAL; String name = intf.getName(); int n = 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, use com.sun.proxy package proxyPkg = ReflectUtil.PROXY_PACKAGE + "."; } /* * Choose a name for the proxy class to generate. */ long num = nextUniqueNumber.getAndIncrement(); String proxyName = proxyPkg + proxyClassNamePrefix + num; /*核心 * Generate the specified proxy class. */ byte[] proxyClassFile = ProxyGenerator.generateProxyClass( proxyName, interfaces, accessFlags); try { 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()); } } }
- GenerateClassFile()分析:可参考https://www.cnblogs.com/liuyun1995/p/8144706.html
private byte[] generateClassFile() { this.addProxyMethod(hashCodeMethod, Object.class); this.addProxyMethod(equalsMethod, Object.class); this.addProxyMethod(toStringMethod, Object.class); Class[] var1 = this.interfaces; int var2 = var1.length; int var3; Class var4; for(var3 = 0; var3 < var2; ++var3) { var4 = var1[var3]; Method[] var5 = var4.getMethods(); int var6 = var5.length; for(int var7 = 0; var7 < var6; ++var7) { Method var8 = var5[var7]; this.addProxyMethod(var8, var4); } } Iterator var11 = this.proxyMethods.values().iterator(); List var12; while(var11.hasNext()) { var12 = (List)var11.next(); checkReturnTypes(var12); } Iterator var15; try { this.methods.add(this.generateConstructor()); var11 = this.proxyMethods.values().iterator(); while(var11.hasNext()) { var12 = (List)var11.next(); var15 = var12.iterator(); while(var15.hasNext()) { ProxyGenerator.ProxyMethod var16 = (ProxyGenerator.ProxyMethod)var15.next(); this.fields.add(new ProxyGenerator.FieldInfo(var16.methodFieldName, "Ljava/lang/reflect/Method;", 10)); this.methods.add(var16.generateMethod()); } } this.methods.add(this.generateStaticInitializer()); } catch (IOException var10) { throw new InternalError("unexpected I/O Exception", var10); } if (this.methods.size() > 65535) { throw new IllegalArgumentException("method limit exceeded"); } else if (this.fields.size() > 65535) { throw new IllegalArgumentException("field limit exceeded"); } else { this.cp.getClass(dotToSlash(this.className)); this.cp.getClass("java/lang/reflect/Proxy"); var1 = this.interfaces; var2 = var1.length; for(var3 = 0; var3 < var2; ++var3) { var4 = var1[var3]; this.cp.getClass(dotToSlash(var4.getName())); } this.cp.setReadOnly(); ByteArrayOutputStream var13 = new ByteArrayOutputStream(); DataOutputStream var14 = new DataOutputStream(var13); try { var14.writeInt(-889275714);//魔数 var14.writeShort(0);//此版本号 var14.writeShort(49);//主版本号 this.cp.write(var14);//常量池 var14.writeShort(this.accessFlags);//访问修饰符 var14.writeShort(this.cp.getClass(dotToSlash(this.className)));//类索引 var14.writeShort(this.cp.getClass("java/lang/reflect/Proxy"));//父类索引 var14.writeShort(this.interfaces.length);//接口个数 Class[] var17 = this.interfaces;//接口内容 int var18 = var17.length; for(int var19 = 0; var19 < var18; ++var19) { Class var22 = var17[var19]; var14.writeShort(this.cp.getClass(dotToSlash(var22.getName()))); } var14.writeShort(this.fields.size());//域个数 var15 = this.fields.iterator();//域 while(var15.hasNext()) { ProxyGenerator.FieldInfo var20 = (ProxyGenerator.FieldInfo)var15.next(); var20.write(var14); } var14.writeShort(this.methods.size());//方法个数 var15 = this.methods.iterator();//方法 while(var15.hasNext()) { ProxyGenerator.MethodInfo var21 = (ProxyGenerator.MethodInfo)var15.next(); var21.write(var14); } var14.writeShort(0); return var13.toByteArray(); } catch (IOException var9) { throw new InternalError("unexpected I/O Exception", var9); } } }
任重而道远
思考与想法都可以时刻记录下来