📄 rmic.java
字号:
dispatch.visitTypeInsn (C.NEW, typeArg(SkeletonMismatchException.class)); dispatch.visitInsn(C.DUP); dispatch.visitLdcInsn("interface hash mismatch"); dispatch.visitMethodInsn (C.INVOKESPECIAL, Type.getInternalName(SkeletonMismatchException.class), "<init>", Type.getMethodDescriptor (Type.VOID_TYPE, new Type[] { Type.getType(String.class) })); dispatch.visitInsn(C.ATHROW); // opnum has been set dispatch.visitLabel(opnumSet); dispatch.visitVarInsn(C.ALOAD, var.get("remoteobj")); dispatch.visitTypeInsn(C.CHECKCAST, typeArg(clazz)); dispatch.visitVarInsn(C.ASTORE, var.get("remoteobj")); Label deflt = new Label(); Label[] methLabels = new Label[remotemethods.length]; for (int i = 0; i < methLabels.length; i++) methLabels[i] = new Label(); // switch on opnum dispatch.visitVarInsn(C.ILOAD, var.get("opnum")); dispatch.visitTableSwitchInsn (0, remotemethods.length - 1, deflt, methLabels); // Method dispatch for (int i = 0; i < remotemethods.length; i++) { dispatch.visitLabel(methLabels[i]); Method m = remotemethods[i].meth; generateMethodSkel(dispatch, m, var); } dispatch.visitLabel(deflt); dispatch.visitTypeInsn(C.NEW, typeArg(UnmarshalException.class)); dispatch.visitInsn(C.DUP); dispatch.visitLdcInsn("invalid method number"); dispatch.visitMethodInsn (C.INVOKESPECIAL, Type.getInternalName(UnmarshalException.class), "<init>", Type.getMethodDescriptor (Type.VOID_TYPE, new Type[] { Type.getType(String.class) })); dispatch.visitInsn(C.ATHROW); dispatch.visitMaxs(-1, -1); skel.visitEnd(); byte[] classData = skel.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 generateMethodSkel(CodeVisitor cv, Method m, Variables var) { Class[] sig = m.getParameterTypes(); Label readArgs = new Label(); cv.visitLabel(readArgs); boolean needcastcheck = false; // ObjectInput in = call.getInputStream(); cv.visitVarInsn(C.ALOAD, var.get("remotecall")); cv.visitMethodInsn (C.INVOKEINTERFACE, Type.getInternalName(RemoteCall.class), "getInputStream", Type.getMethodDescriptor (Type.getType(ObjectInput.class), new Type[] {})); cv.visitVarInsn(C.ASTORE, var.allocate("objectinput")); for (int i = 0; i < sig.length; i++) { // dup input stream cv.visitVarInsn(C.ALOAD, var.get("objectinput")); Class readCls = sig[i].isPrimitive() ? sig[i] : Object.class; // in.readFoo() cv.visitMethodInsn (C.INVOKEINTERFACE, Type.getInternalName(ObjectInput.class), readMethod(sig[i]), Type.getMethodDescriptor (Type.getType(readCls), new Type [] {})); if (! sig[i].isPrimitive() && ! sig[i].equals(Object.class)) { needcastcheck = true; cv.visitTypeInsn(C.CHECKCAST, typeArg(sig[i])); } // store arg in variable cv.visitVarInsn (storeOpcode(sig[i]), var.allocate(param(m, i), size(sig[i]))); } var.deallocate("objectinput"); Label doCall = new Label(); Label closeInput = new Label(); cv.visitJumpInsn(C.JSR, closeInput); cv.visitJumpInsn(C.GOTO, doCall); // throw new UnmarshalException Label handler = new Label(); cv.visitLabel(handler); cv.visitVarInsn(C.ASTORE, var.allocate("exception")); cv.visitTypeInsn(C.NEW, typeArg(UnmarshalException.class)); cv.visitInsn(C.DUP); cv.visitLdcInsn("error unmarshalling arguments"); cv.visitVarInsn(C.ALOAD, var.deallocate("exception")); cv.visitMethodInsn (C.INVOKESPECIAL, Type.getInternalName(UnmarshalException.class), "<init>", Type.getMethodDescriptor (Type.VOID_TYPE, new Type[] { Type.getType(String.class), Type.getType(Exception.class) })); cv.visitVarInsn(C.ASTORE, var.allocate("toThrow")); cv.visitJumpInsn(C.JSR, closeInput); cv.visitVarInsn(C.ALOAD, var.get("toThrow")); cv.visitInsn(C.ATHROW); cv.visitTryCatchBlock (readArgs, handler, handler, Type.getInternalName(IOException.class)); if (needcastcheck) { cv.visitTryCatchBlock (readArgs, handler, handler, Type.getInternalName(ClassCastException.class)); } // finally block cv.visitLabel(closeInput); cv.visitVarInsn(C.ASTORE, var.allocate("retAddress")); cv.visitVarInsn(C.ALOAD, var.get("remotecall")); cv.visitMethodInsn (C.INVOKEINTERFACE, Type.getInternalName(RemoteCall.class), "releaseInputStream", Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {})); cv.visitVarInsn(C.RET, var.deallocate("retAddress")); var.deallocate("toThrow"); // do the call using args stored as variables cv.visitLabel(doCall); cv.visitVarInsn(C.ALOAD, var.get("remoteobj")); for (int i = 0; i < sig.length; i++) cv.visitVarInsn(loadOpcode(sig[i]), var.deallocate(param(m, i))); cv.visitMethodInsn (C.INVOKEVIRTUAL, Type.getInternalName(clazz), m.getName(), Type.getMethodDescriptor(m)); Class returntype = m.getReturnType(); if (! returntype.equals(Void.TYPE)) { cv.visitVarInsn (storeOpcode(returntype), var.allocate("result", size(returntype))); } // write result to result stream Label writeResult = new Label(); cv.visitLabel(writeResult); cv.visitVarInsn(C.ALOAD, var.get("remotecall")); cv.visitInsn(C.ICONST_1); cv.visitMethodInsn (C.INVOKEINTERFACE, Type.getInternalName(RemoteCall.class), "getResultStream", Type.getMethodDescriptor (Type.getType(ObjectOutput.class), new Type[] { Type.BOOLEAN_TYPE })); if (! returntype.equals(Void.TYPE)) { // out.writeFoo(result) cv.visitVarInsn(loadOpcode(returntype), var.deallocate("result")); Class writeCls = returntype.isPrimitive() ? returntype : Object.class; cv.visitMethodInsn (C.INVOKEINTERFACE, Type.getInternalName(ObjectOutput.class), writeMethod(returntype), Type.getMethodDescriptor (Type.VOID_TYPE, new Type[] { Type.getType(writeCls) })); } cv.visitInsn(C.RETURN); // throw new MarshalException Label marshalHandler = new Label(); cv.visitLabel(marshalHandler); cv.visitVarInsn(C.ASTORE, var.allocate("exception")); cv.visitTypeInsn(C.NEW, typeArg(MarshalException.class)); cv.visitInsn(C.DUP); cv.visitLdcInsn("error marshalling return"); cv.visitVarInsn(C.ALOAD, var.deallocate("exception")); cv.visitMethodInsn (C.INVOKESPECIAL, Type.getInternalName(MarshalException.class), "<init>", Type.getMethodDescriptor (Type.VOID_TYPE, new Type[] { Type.getType(String.class), Type.getType(Exception.class) })); cv.visitInsn(C.ATHROW); cv.visitTryCatchBlock (writeResult, marshalHandler, marshalHandler, Type.getInternalName(IOException.class)); } private static String typeArg(Class cls) { if (cls.isArray()) return Type.getDescriptor(cls); return Type.getInternalName(cls); } private static String readMethod(Class cls) { if (cls.equals(Void.TYPE)) throw new IllegalArgumentException("can not read void"); String method; if (cls.equals(Boolean.TYPE)) method = "readBoolean"; else if (cls.equals(Byte.TYPE)) method = "readByte"; else if (cls.equals(Character.TYPE)) method = "readChar"; else if (cls.equals(Short.TYPE)) method = "readShort"; else if (cls.equals(Integer.TYPE)) method = "readInt"; else if (cls.equals(Long.TYPE)) method = "readLong"; else if (cls.equals(Float.TYPE)) method = "readFloat"; else if (cls.equals(Double.TYPE)) method = "readDouble"; else method = "readObject"; return method; } private static String writeMethod(Class cls) { if (cls.equals(Void.TYPE)) throw new IllegalArgumentException("can not read void"); String method; if (cls.equals(Boolean.TYPE)) method = "writeBoolean"; else if (cls.equals(Byte.TYPE)) method = "writeByte"; else if (cls.equals(Character.TYPE)) method = "writeChar"; else if (cls.equals(Short.TYPE)) method = "writeShort"; else if (cls.equals(Integer.TYPE)) method = "writeInt"; else if (cls.equals(Long.TYPE)) method = "writeLong"; else if (cls.equals(Float.TYPE)) method = "writeFloat"; else if (cls.equals(Double.TYPE)) method = "writeDouble"; else method = "writeObject"; return method; } private static int returnOpcode(Class cls) { int returncode; if (cls.equals(Boolean.TYPE)) returncode = C.IRETURN; else if (cls.equals(Byte.TYPE)) returncode = C.IRETURN; else if (cls.equals(Character.TYPE)) returncode = C.IRETURN; else if (cls.equals(Short.TYPE)) returncode = C.IRETURN; else if (cls.equals(Integer.TYPE)) returncode = C.IRETURN; else if (cls.equals(Long.TYPE)) returncode = C.LRETURN; else if (cls.equals(Float.TYPE)) returncode = C.FRETURN; else if (cls.equals(Double.TYPE)) returncode = C.DRETURN; else if (cls.equals(Void.TYPE)) returncode = C.RETURN; else returncode = C.ARETURN; return returncode; } private static int loadOpcode(Class cls) { if (cls.equals(Void.TYPE)) throw new IllegalArgumentException("can not load void"); int loadcode; if (cls.equals(Boolean.TYPE)) loadcode = C.ILOAD; else if (cls.equals(Byte.TYPE)) loadcode = C.ILOAD; else if (cls.equals(Character.TYPE)) loadcode = C.ILOAD; else if (cls.equals(Short.TYPE)) loadcode = C.ILOAD; else if (cls.equals(Integer.TYPE)) loadcode = C.ILOAD; else if (cls.equals(Long.TYPE)) loadcode = C.LLOAD; else if (cls.equals(Float.TYPE)) loadcode = C.FLOAD; else if (cls.equals(Double.TYPE)) loadcode = C.DLOAD; else loadcode = C.ALOAD; return loadcode; } private static int storeOpcode(Class cls) { if (cls.equals(Void.TYPE)) throw new IllegalArgumentException("can not load void"); int storecode; if (cls.equals(Boolean.TYPE)) storecode = C.ISTORE; else if (cls.equals(Byte.TYPE)) storecode = C.ISTORE; else if (cls.equals(Character.TYPE)) storecode = C.ISTORE; else if (cls.equals(Short.TYPE)) storecode = C.ISTORE; else if (cls.equals(Integer.TYPE)) storecode = C.ISTORE; else if (cls.equals(Long.TYPE)) storecode = C.LSTORE; else if (cls.equals(Float.TYPE)) storecode = C.FSTORE; else if (cls.equals(Double.TYPE)) storecode = C.DSTORE; else storecode = C.ASTORE; return storecode; } private static String unboxMethod(Class primitive) { if (! primitive.isPrimitive()) throw new IllegalArgumentException("can not unbox nonprimitive"); String method; if (primitive.equals(Boolean.TYPE)) method = "booleanValue"; else if (primitive.equals(Byte.TYPE)) method = "byteValue"; else if (primitive.equals(Character.TYPE)) method = "charValue"; else if (primitive.equals(Short.TYPE)) method = "shortValue"; else if (primitive.equals(Integer.TYPE)) method = "intValue"; else if (primitive.equals(Long.TYPE)) method = "longValue"; else if (primitive.equals(Float.TYPE)) method = "floatValue"; else if (primitive.equals(Double.TYPE))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -