📄 rmic.java
字号:
// interface hash is fourth arg code.visitFieldInsn (C.GETSTATIC, classInternalName, "interfaceHash", Type.LONG_TYPE.getDescriptor()); code.visitMethodInsn (C.INVOKEINTERFACE, Type.getInternalName(RemoteRef.class), "newCall", Type.getMethodDescriptor (Type.getType(RemoteCall.class), new Type[] { Type.getType(RemoteObject.class), Type.getType(Operation[].class), Type.INT_TYPE, Type.LONG_TYPE })); // store call object on stack and leave copy on stack var.allocate("call"); code.visitInsn(C.DUP); code.visitVarInsn(C.ASTORE, var.get("call")); Label beginArgumentTryBlock = new Label(); code.visitLabel(beginArgumentTryBlock); // ObjectOutput out = call.getOutputStream(); code.visitMethodInsn (C.INVOKEINTERFACE, Type.getInternalName(RemoteCall.class), "getOutputStream", Type.getMethodDescriptor (Type.getType(ObjectOutput.class), new Type[] {})); for (int j = 0; j < sig.length; j++) { // dup the ObjectOutput code.visitInsn(C.DUP); // get j'th arg to remote method code.visitVarInsn(loadOpcode(sig[j]), var.get(param(m, j))); Class argCls = sig[j].isPrimitive() ? sig[j] : Object.class; // out.writeFoo code.visitMethodInsn (C.INVOKEINTERFACE, Type.getInternalName(ObjectOutput.class), writeMethod(sig[j]), Type.getMethodDescriptor (Type.VOID_TYPE, new Type[] { Type.getType(argCls) })); } // pop ObjectOutput code.visitInsn(C.POP); Label iohandler = new Label(); Label endArgumentTryBlock = new Label(); code.visitJumpInsn(C.GOTO, endArgumentTryBlock); code.visitLabel(iohandler); // throw new MarshalException(msg, ioexception); code.visitVarInsn(C.ASTORE, var.allocate("exception")); code.visitTypeInsn(C.NEW, typeArg(MarshalException.class)); code.visitInsn(C.DUP); code.visitLdcInsn("error marshalling arguments"); code.visitVarInsn(C.ALOAD, var.deallocate("exception")); code.visitMethodInsn (C.INVOKESPECIAL, Type.getInternalName(MarshalException.class), "<init>", Type.getMethodDescriptor (Type.VOID_TYPE, new Type[] { Type.getType(String.class), Type.getType(Exception.class) })); code.visitInsn(C.ATHROW); code.visitLabel(endArgumentTryBlock); code.visitTryCatchBlock (beginArgumentTryBlock, iohandler, iohandler, Type.getInternalName(IOException.class)); // this.ref.invoke(call) code.visitVarInsn(C.ALOAD, var.get("this")); code.visitFieldInsn (C.GETFIELD, Type.getInternalName(RemoteObject.class), "ref", Type.getDescriptor(RemoteRef.class)); code.visitVarInsn(C.ALOAD, var.get("call")); code.visitMethodInsn (C.INVOKEINTERFACE, Type.getInternalName(RemoteRef.class), "invoke", Type.getMethodDescriptor (Type.VOID_TYPE, new Type[] { Type.getType(RemoteCall.class) })); // handle return value boolean needcastcheck = false; Label beginReturnTryCatch = new Label(); code.visitLabel(beginReturnTryCatch); int returncode = returnOpcode(returntype); if (! returntype.equals(Void.TYPE)) { // call.getInputStream() code.visitVarInsn(C.ALOAD, var.get("call")); code.visitMethodInsn (C.INVOKEINTERFACE, Type.getInternalName(RemoteCall.class), "getInputStream", Type.getMethodDescriptor (Type.getType(ObjectInput.class), new Type[] {})); Class readCls = returntype.isPrimitive() ? returntype : Object.class; code.visitMethodInsn (C.INVOKEINTERFACE, Type.getInternalName(ObjectInput.class), readMethod(returntype), Type.getMethodDescriptor (Type.getType(readCls), new Type[] {})); boolean castresult = false; if (! returntype.isPrimitive()) { if (! returntype.equals(Object.class)) castresult = true; else needcastcheck = true; } if (castresult) code.visitTypeInsn(C.CHECKCAST, typeArg(returntype)); // leave result on stack for return } // this.ref.done(call) code.visitVarInsn(C.ALOAD, var.get("this")); code.visitFieldInsn (C.GETFIELD, Type.getInternalName(RemoteObject.class), "ref", Type.getDescriptor(RemoteRef.class)); code.visitVarInsn(C.ALOAD, var.deallocate("call")); code.visitMethodInsn (C.INVOKEINTERFACE, Type.getInternalName(RemoteRef.class), "done", Type.getMethodDescriptor (Type.VOID_TYPE, new Type[] { Type.getType(RemoteCall.class) })); // return; or return result; code.visitInsn(returncode); // exception handler Label handler = new Label(); code.visitLabel(handler); code.visitVarInsn(C.ASTORE, var.allocate("exception")); // throw new UnmarshalException(msg, e) code.visitTypeInsn(C.NEW, typeArg(UnmarshalException.class)); code.visitInsn(C.DUP); code.visitLdcInsn("error unmarshalling return"); code.visitVarInsn(C.ALOAD, var.deallocate("exception")); code.visitMethodInsn (C.INVOKESPECIAL, Type.getInternalName(UnmarshalException.class), "<init>", Type.getMethodDescriptor (Type.VOID_TYPE, new Type[] { Type.getType(String.class), Type.getType(Exception.class) })); code.visitInsn(C.ATHROW); Label endReturnTryCatch = new Label(); // catch IOException code.visitTryCatchBlock (beginReturnTryCatch, handler, handler, Type.getInternalName(IOException.class)); if (needcastcheck) { // catch ClassNotFoundException code.visitTryCatchBlock (beginReturnTryCatch, handler, handler, Type.getInternalName(ClassNotFoundException.class)); } } Label rethrowHandler = new Label(); code.visitLabel(rethrowHandler); // rethrow declared exceptions code.visitInsn(C.ATHROW); boolean needgeneral = true; for (int j = 0; j < except.length; j++) { if (except[j] == Exception.class) needgeneral = false; } for (int j = 0; j < except.length; j++) { code.visitTryCatchBlock (methodTryBegin, rethrowHandler, rethrowHandler, Type.getInternalName(except[j])); } if (needgeneral) { // rethrow unchecked exceptions code.visitTryCatchBlock (methodTryBegin, rethrowHandler, rethrowHandler, Type.getInternalName(RuntimeException.class)); Label generalHandler = new Label(); code.visitLabel(generalHandler); String msg = "undeclared checked exception"; // throw new java.rmi.UnexpectedException(msg, e) code.visitVarInsn(C.ASTORE, var.allocate("exception")); code.visitTypeInsn(C.NEW, typeArg(UnexpectedException.class)); code.visitInsn(C.DUP); code.visitLdcInsn(msg); code.visitVarInsn(C.ALOAD, var.deallocate("exception")); code.visitMethodInsn (C.INVOKESPECIAL, Type.getInternalName(UnexpectedException.class), "<init>", Type.getMethodDescriptor (Type.VOID_TYPE, new Type [] { Type.getType(String.class), Type.getType(Exception.class) })); code.visitInsn(C.ATHROW); code.visitTryCatchBlock (methodTryBegin, rethrowHandler, generalHandler, Type.getInternalName(Exception.class)); } code.visitMaxs(-1, -1); } stub.visitEnd(); byte[] classData = stub.toByteArray(); if (file.exists()) file.delete(); if (file.getParentFile() != null) file.getParentFile().mkdirs(); FileOutputStream fos = new FileOutputStream(file); fos.write(classData); fos.flush(); fos.close(); } private void generateSkel() throws IOException { skelname = fullclassname + "_Skel"; String skelclassname = classname + "_Skel"; File file = new File(destination == null ? "" : destination + File.separator + skelname.replace('.', File.separatorChar) + ".class"); if (verbose) System.out.println("[Generating class " + skelname + "]"); final ClassWriter skel = new ClassWriter(true); classInternalName = skelname.replace('.', '/'); skel.visit (C.V1_1, C.ACC_PUBLIC + C.ACC_FINAL, classInternalName, Type.getInternalName(Object.class), new String[] { Type.getType(Skeleton.class).getInternalName() }, null); skel.visitField (C.ACC_PRIVATE + C.ACC_STATIC + C.ACC_FINAL, "interfaceHash", Type.LONG_TYPE.getDescriptor(), new Long(RMIHashes.getInterfaceHash(clazz)), null); skel.visitField (C.ACC_PRIVATE + C.ACC_STATIC + C.ACC_FINAL, "operations", Type.getDescriptor(Operation[].class), null, null); CodeVisitor clinit = skel.visitMethod (C.ACC_STATIC, "<clinit>", Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {}), null, null); fillOperationArray(clinit); clinit.visitInsn(C.RETURN); clinit.visitMaxs(-1, -1); // no arg public constructor CodeVisitor init = skel.visitMethod (C.ACC_PUBLIC, "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {}), null, null); init.visitVarInsn(C.ALOAD, 0); init.visitMethodInsn (C.INVOKESPECIAL, Type.getInternalName(Object.class), "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {})); init.visitInsn(C.RETURN); init.visitMaxs(-1, -1); /* * public Operation[] getOperations() * returns a clone of the operations array */ CodeVisitor getOp = skel.visitMethod (C.ACC_PUBLIC, "getOperations", Type.getMethodDescriptor (Type.getType(Operation[].class), new Type[] {}), null, null); getOp.visitFieldInsn (C.GETSTATIC, classInternalName, "operations", Type.getDescriptor(Operation[].class)); getOp.visitMethodInsn (C.INVOKEVIRTUAL, Type.getInternalName(Object.class), "clone", Type.getMethodDescriptor(Type.getType(Object.class), new Type[] {})); getOp.visitTypeInsn(C.CHECKCAST, typeArg(Operation[].class)); getOp.visitInsn(C.ARETURN); getOp.visitMaxs(-1, -1); // public void dispatch(Remote, RemoteCall, int opnum, long hash) CodeVisitor dispatch = skel.visitMethod (C.ACC_PUBLIC, "dispatch", Type.getMethodDescriptor (Type.VOID_TYPE, new Type[] { Type.getType(Remote.class), Type.getType(RemoteCall.class), Type.INT_TYPE, Type.LONG_TYPE }), new String[] { Type.getInternalName(Exception.class) }, null); Variables var = new Variables(); var.declare("this"); var.declare("remoteobj"); var.declare("remotecall"); var.declare("opnum"); var.declareWide("hash"); /* * if opnum >= 0 * XXX it is unclear why there is handling of negative opnums */ dispatch.visitVarInsn(C.ILOAD, var.get("opnum")); Label nonNegativeOpnum = new Label(); Label opnumSet = new Label(); dispatch.visitJumpInsn(C.IFGE, nonNegativeOpnum); for (int i = 0; i < remotemethods.length; i++) { // assign opnum if hash matches supplied hash dispatch.visitVarInsn(C.LLOAD, var.get("hash")); dispatch.visitLdcInsn(new Long(remotemethods[i].hash)); Label notIt = new Label(); dispatch.visitInsn(C.LCMP); dispatch.visitJumpInsn(C.IFNE, notIt); // opnum = <opnum> dispatch.visitLdcInsn(new Integer(i)); dispatch.visitVarInsn(C.ISTORE, var.get("opnum")); dispatch.visitJumpInsn(C.GOTO, opnumSet); dispatch.visitLabel(notIt); } // throw new SkeletonMismatchException Label mismatch = new Label(); dispatch.visitJumpInsn(C.GOTO, mismatch); dispatch.visitLabel(nonNegativeOpnum); // if opnum is already set, check that the hash matches the interface dispatch.visitVarInsn(C.LLOAD, var.get("hash")); dispatch.visitFieldInsn (C.GETSTATIC, classInternalName, "interfaceHash", Type.LONG_TYPE.getDescriptor()); dispatch.visitInsn(C.LCMP); dispatch.visitJumpInsn(C.IFEQ, opnumSet); dispatch.visitLabel(mismatch);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -