📄 rmic.java
字号:
// instantiate operation and leave a copy on the stack clinit.visitTypeInsn(C.NEW, typeArg(Operation.class)); clinit.visitInsn(C.DUP); clinit.visitLdcInsn(desc.toString()); clinit.visitMethodInsn (C.INVOKESPECIAL, Type.getInternalName(Operation.class), "<init>", Type.getMethodDescriptor (Type.VOID_TYPE, new Type[] { Type.getType(String.class) })); // store in operations array clinit.visitInsn(C.AASTORE); } } private void generateStaticMethodObjs(CodeVisitor clinit) { for (int i = 0; i < remotemethods.length; i++) { Method m = remotemethods[i].meth; /* * $method_<i>m.getName()</i>_<i>i</i> = * <i>m.getDeclaringClass()</i>.class.getMethod * (m.getName(), m.getParameterType()) */ String methodVar = "$method_" + m.getName() + "_" + i; generateClassConstant(clinit, m.getDeclaringClass()); clinit.visitLdcInsn(m.getName()); generateClassArray(clinit, m.getParameterTypes()); clinit.visitMethodInsn (C.INVOKEVIRTUAL, Type.getInternalName(Class.class), "getMethod", Type.getMethodDescriptor (Type.getType(Method.class), new Type[] { Type.getType(String.class), Type.getType(Class[].class) })); clinit.visitFieldInsn (C.PUTSTATIC, classInternalName, methodVar, Type.getDescriptor(Method.class)); } } private void generateStub() throws IOException { stubname = fullclassname + "_Stub"; String stubclassname = classname + "_Stub"; File file = new File((destination == null ? "." : destination) + File.separator + stubname.replace('.', File.separatorChar) + ".class"); if (verbose) System.out.println("[Generating class " + stubname + "]"); final ClassWriter stub = new ClassWriter(true); classInternalName = stubname.replace('.', '/'); final String superInternalName = Type.getType(RemoteStub.class).getInternalName(); String[] remoteInternalNames = internalNameArray((Class[]) mRemoteInterfaces.toArray(new Class[] {})); stub.visit (C.V1_2, C.ACC_PUBLIC + C.ACC_FINAL, classInternalName, superInternalName, remoteInternalNames, null); if (need12Stubs) { stub.visitField (C.ACC_PRIVATE + C.ACC_STATIC + C.ACC_FINAL, "serialVersionUID", Type.LONG_TYPE.getDescriptor(), new Long(2L), null); } if (need11Stubs) { stub.visitField (C.ACC_PRIVATE + C.ACC_STATIC + C.ACC_FINAL, "interfaceHash", Type.LONG_TYPE.getDescriptor(), new Long(RMIHashes.getInterfaceHash(clazz)), null); if (need12Stubs) { stub.visitField (C.ACC_PRIVATE + C.ACC_STATIC, "useNewInvoke", Type.BOOLEAN_TYPE.getDescriptor(), null, null); } stub.visitField (C.ACC_PRIVATE + C.ACC_STATIC + C.ACC_FINAL, "operations", Type.getDescriptor(Operation[].class), null, null); } // Set of method references. if (need12Stubs) { for (int i = 0; i < remotemethods.length; i++) { Method m = remotemethods[i].meth; String slotName = "$method_" + m.getName() + "_" + i; stub.visitField (C.ACC_PRIVATE + C.ACC_STATIC, slotName, Type.getDescriptor(Method.class), null, null); } } CodeVisitor clinit = stub.visitMethod (C.ACC_STATIC, "<clinit>", Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {}), null, null); if (need11Stubs) { fillOperationArray(clinit); if (! need12Stubs) clinit.visitInsn(C.RETURN); } if (need12Stubs) { // begin of try Label begin = new Label(); // beginning of catch Label handler = new Label(); clinit.visitLabel(begin); // Initialize the methods references. if (need11Stubs) { /* * RemoteRef.class.getMethod("invoke", new Class[] { * Remote.class, Method.class, Object[].class, long.class }) */ generateClassConstant(clinit, RemoteRef.class); clinit.visitLdcInsn("invoke"); generateClassArray (clinit, new Class[] { Remote.class, Method.class, Object[].class, long.class }); clinit.visitMethodInsn (C.INVOKEVIRTUAL, Type.getInternalName(Class.class), "getMethod", Type.getMethodDescriptor (Type.getType(Method.class), new Type[] { Type.getType(String.class), Type.getType(Class[].class) })); // useNewInvoke = true clinit.visitInsn(C.ICONST_1); clinit.visitFieldInsn (C.PUTSTATIC, classInternalName, "useNewInvoke", Type.BOOLEAN_TYPE.getDescriptor()); } generateStaticMethodObjs(clinit); // jump past handler clinit.visitInsn(C.RETURN); clinit.visitLabel(handler); if (need11Stubs) { // useNewInvoke = false clinit.visitInsn(C.ICONST_0); clinit.visitFieldInsn (C.PUTSTATIC, classInternalName, "useNewInvoke", Type.BOOLEAN_TYPE.getDescriptor()); clinit.visitInsn(C.RETURN); } else { // throw NoSuchMethodError clinit.visitTypeInsn(C.NEW, typeArg(NoSuchMethodError.class)); clinit.visitInsn(C.DUP); clinit.visitLdcInsn("stub class initialization failed"); clinit.visitMethodInsn (C.INVOKESPECIAL, Type.getInternalName(NoSuchMethodError.class), "<init>", Type.getMethodDescriptor (Type.VOID_TYPE, new Type[] { Type.getType(String.class) })); clinit.visitInsn(C.ATHROW); } clinit.visitTryCatchBlock (begin, handler, handler, Type.getInternalName(NoSuchMethodException.class)); } clinit.visitMaxs(-1, -1); generateClassForNamer(stub); // Constructors if (need11Stubs) { // no arg public constructor CodeVisitor code = stub.visitMethod (C.ACC_PUBLIC, "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {}), null, null); code.visitVarInsn(C.ALOAD, 0); code.visitMethodInsn (C.INVOKESPECIAL, superInternalName, "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {})); code.visitInsn(C.RETURN); code.visitMaxs(-1, -1); } // public RemoteRef constructor CodeVisitor constructor = stub.visitMethod (C.ACC_PUBLIC, "<init>", Type.getMethodDescriptor (Type.VOID_TYPE, new Type[] {Type.getType(RemoteRef.class)}), null, null); constructor.visitVarInsn(C.ALOAD, 0); constructor.visitVarInsn(C.ALOAD, 1); constructor.visitMethodInsn (C.INVOKESPECIAL, superInternalName, "<init>", Type.getMethodDescriptor (Type.VOID_TYPE, new Type[] {Type.getType(RemoteRef.class)})); constructor.visitInsn(C.RETURN); constructor.visitMaxs(-1, -1); // Method implementations for (int i = 0; i < remotemethods.length; i++) { Method m = remotemethods[i].meth; Class[] sig = m.getParameterTypes(); Class returntype = m.getReturnType(); Class[] except = sortExceptions ((Class[]) remotemethods[i].exceptions.toArray(new Class[0])); CodeVisitor code = stub.visitMethod (C.ACC_PUBLIC, m.getName(), Type.getMethodDescriptor(Type.getType(returntype), typeArray(sig)), internalNameArray(typeArray(except)), null); final Variables var = new Variables(); // this and parameters are the declared vars var.declare("this"); for (int j = 0; j < sig.length; j++) var.declare(param(m, j), size(sig[j])); Label methodTryBegin = new Label(); code.visitLabel(methodTryBegin); if (need12Stubs) { Label oldInvoke = new Label(); if (need11Stubs) { // if not useNewInvoke jump to old invoke code.visitFieldInsn (C.GETSTATIC, classInternalName, "useNewInvoke", Type.getDescriptor(boolean.class)); code.visitJumpInsn(C.IFEQ, oldInvoke); } // this.ref code.visitVarInsn(C.ALOAD, var.get("this")); code.visitFieldInsn (C.GETFIELD, Type.getInternalName(RemoteObject.class), "ref", Type.getDescriptor(RemoteRef.class)); // "this" is first arg to invoke code.visitVarInsn(C.ALOAD, var.get("this")); // method object is second arg to invoke String methName = "$method_" + m.getName() + "_" + i; code.visitFieldInsn (C.GETSTATIC, classInternalName, methName, Type.getDescriptor(Method.class)); // args to remote method are third arg to invoke if (sig.length == 0) code.visitInsn(C.ACONST_NULL); else { // create arg Object[] (with boxed primitives) and push it code.visitLdcInsn(new Integer(sig.length)); code.visitTypeInsn(C.ANEWARRAY, typeArg(Object.class)); var.allocate("argArray"); code.visitVarInsn(C.ASTORE, var.get("argArray")); for (int j = 0; j < sig.length; j++) { int size = size(sig[j]); int insn = loadOpcode(sig[j]); Class box = sig[j].isPrimitive() ? box(sig[j]) : null; code.visitVarInsn(C.ALOAD, var.get("argArray")); code.visitLdcInsn(new Integer(j)); // put argument on stack if (box != null) { code.visitTypeInsn(C.NEW, typeArg(box)); code.visitInsn(C.DUP); code.visitVarInsn(insn, var.get(param(m, j))); code.visitMethodInsn (C.INVOKESPECIAL, Type.getInternalName(box), "<init>", Type.getMethodDescriptor (Type.VOID_TYPE, new Type[] { Type.getType(sig[j]) })); } else code.visitVarInsn(insn, var.get(param(m, j))); code.visitInsn(C.AASTORE); } code.visitVarInsn(C.ALOAD, var.deallocate("argArray")); } // push remote operation opcode code.visitLdcInsn(new Long(remotemethods[i].hash)); code.visitMethodInsn (C.INVOKEINTERFACE, Type.getInternalName(RemoteRef.class), "invoke", Type.getMethodDescriptor (Type.getType(Object.class), new Type[] { Type.getType(Remote.class), Type.getType(Method.class), Type.getType(Object[].class), Type.LONG_TYPE })); if (! returntype.equals(Void.TYPE)) { int retcode = returnOpcode(returntype); Class boxCls = returntype.isPrimitive() ? box(returntype) : null; code.visitTypeInsn (C.CHECKCAST, typeArg(boxCls == null ? returntype : boxCls)); if (returntype.isPrimitive()) { // unbox code.visitMethodInsn (C.INVOKEVIRTUAL, Type.getType(boxCls).getInternalName(), unboxMethod(returntype), Type.getMethodDescriptor (Type.getType(returntype), new Type[] {})); } code.visitInsn(retcode); } else code.visitInsn(C.RETURN); if (need11Stubs) code.visitLabel(oldInvoke); } if (need11Stubs) { // this.ref.newCall(this, operations, index, interfaceHash) code.visitVarInsn(C.ALOAD, var.get("this")); code.visitFieldInsn (C.GETFIELD, Type.getInternalName(RemoteObject.class), "ref", Type.getDescriptor(RemoteRef.class)); // "this" is first arg to newCall code.visitVarInsn(C.ALOAD, var.get("this")); // operations is second arg to newCall code.visitFieldInsn (C.GETSTATIC, classInternalName, "operations", Type.getDescriptor(Operation[].class)); // method index is third arg code.visitLdcInsn(new Integer(i));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -