📄 stubclassgenerator.java
字号:
for (int j = 0; j < exceptions.length; j++) { cp.addClass(exceptions[j].getName().replace('.', '/')); } } cp.addStringConstant(""); // Add constructor constants... cp.addString("<init>"); cp.addMethodReference(importedObject, "<init>", constructorDescriptor); cp.addMethodReference(importedObject, "com_sun_xlet_execute", executeDescriptor); // For creating UnexpectedException String unexpectedExceptionDescriptor = "(Ljava/lang/String;Ljava/lang/Exception;)V"; cp.addMethodReference("java/rmi/UnexpectedException", "<init>", unexpectedExceptionDescriptor); // Now write out the .class! dos.writeInt(0xcafebabe); dos.writeShort(0x3a); // Minor version, JDK 1.1.3 dos.writeShort(0x2d); // Major version, JDK 1.1.3 // It's what I observed in 1.1.3, which was handy. Nothing magic // about 1.1.3. cp.write(dos); // Constant pool dos.writeShort(0x31); // ACC_SUPER | ACC_PUBLIC | ACC_FINAL // this_class: dos.writeShort(cp.lookupClass(stubName)); // super_class: dos.writeShort(cp.lookupClass(importedObject)); // Interfaces: dos.writeShort(remoteInterfaces.length); for (int i = 0; i < remoteInterfaces.length; i++) { String nm = remoteInterfaces[i]; dos.writeShort(cp.lookupClass(nm.replace('.', '/'))); } // Fields: dos.writeShort(0); // Methods: dos.writeShort(remoteMethods.length + 1); // +1 for constructor // First, the constructor: { dos.writeShort(0x1); // PUBLIC dos.writeShort(cp.lookupString("<init>")); dos.writeShort(cp.lookupString(constructorDescriptor)); dos.writeShort(1); // 1 attribute, the Code attribute dos.writeShort(cp.lookupString("Code")); int codeLen = 7; dos.writeInt(12 + codeLen); // attribute_length dos.writeShort(10); // max_stack; be conservative dos.writeShort(10); // max_locals; be conservative dos.writeInt(codeLen); // The code: dos.write(0x2a); // aload_0, loading this dos.write(0x2b); // aload_1, loading StubObject dos.write(0x2c); // aload_2, loading RemoteHandle dos.write(0xb7); // invokespecial, e.g. super(xxx) of ... dos.writeShort( cp.lookupMethod(importedObject, "<init>", constructorDescriptor)); dos.write(0xb1); // return // The rest of the code attribute: dos.writeShort(0); // exception_table_length dos.writeShort(0); // attribute_count } int executeMethod = cp.lookupMethod(importedObject, "com_sun_xlet_execute", executeDescriptor); // Now the stub methods: for (int i = 0; i < remoteMethods.length; i++) { Method m = remoteMethods[i]; Class[] args = m.getParameterTypes(); //int maxLocals = 1; // 1 for "this" parameter int maxLocals = 2; // 1 for "this" parameter for (int j = 0; j < args.length; j++) { maxLocals += TypeInfo.localSlotsFor(args[j]); } int codeLen = 9; for (int j = 0; j < args.length; j++) { if (args[j].isPrimitive()) { codeLen += 9 + 4; } else { codeLen += 2 + 4; } } codeLen += 3; Class ret = m.getReturnType(); if (Void.TYPE.equals(ret)) { //codeLen += 2; codeLen += 5; } else if (ret.isPrimitive()) { codeLen += 7; } else { codeLen += 4; } int pc_end = codeLen; if (Void.TYPE.equals(ret)) { pc_end -= 4; } else { pc_end -= 1; } // For exception handling. // Each exception catch/throw takes 3 bytes. // For RuntimeException and Exception. codeLen += 6; // For all other catched Exceptions. Class[] exceptions = m.getExceptionTypes(); codeLen += (exceptions.length*3); codeLen += 9; // For creating UnexpectedException dos.writeShort(0x1 | 0x10); // PUBLIC | FINAL dos.writeShort(cp.lookupString(m.getName())); dos.writeShort(cp.lookupString(descriptorFor(remoteMethods[i]))); dos.writeShort(2); // attributes_count dos.writeShort(cp.lookupString("Code")); // 8 for max_stock + max_locals + code_length fields; // 4 for attribute_count and exception_length fields; // Each exception table takes 8 bytes, // There are two additional exceptions: Runtime and Exception. int codeAttributeLen = (8 + codeLen + 4 + (exceptions.length*8) + 16); dos.writeInt(codeAttributeLen); dos.writeShort(10); // max_stack; be conservative dos.writeShort(maxLocals); dos.writeInt(codeLen); // Now the code dos.write(0x2a); // aload_0 dos.write(0x14); // ldc2_w dos.writeShort(cp.lookupLongConstant(methodIDs[i])); dos.write(0x10); // bipush dos.write(args.length); dos.write(0xbd); // anewarray java.lang.Object dos.writeShort(cp.lookupClass("java/lang/Object")); int slot = 1; for (int j = 0; j < args.length; j++) { dos.write(0x59); // dup dos.write(0x10); // bipush dos.write(j); if (args[j].isPrimitive()) { TypeInfo info = TypeInfo.get(args[j]); Class p = info.primitiveWrapper; String pName = p.getName().replace('.', '/'); dos.write(0xbb); // new dos.writeShort(cp.lookupClass(pName)); dos.write(0x59); // dup dos.write(info.loadInstruction); dos.write(slot); // Invoke constructor of primitive wrapper type: dos.write(0xb7); // invokespecial String d = "(" + info.typeDescriptor + ")V"; dos.writeShort(cp.lookupMethod(pName, "<init>", d)); slot += info.localSlots; } else { dos.write(0x19); dos.write(slot); slot++; } dos.write(0x53); // aastore } dos.write(0xb6); // invokevirtual dos.writeShort(executeMethod); if (Void.TYPE.equals(ret)) { dos.write(0x57); // pop //dos.write(0xb1); // return dos.write(0xa7); // goto dos.writeShort(codeLen - pc_end - 1); // target of goto } else if (ret.isPrimitive()) { TypeInfo info = TypeInfo.get(ret); Class wr = info.primitiveWrapper; String wrNm = wr.getName().replace('.', '/'); dos.write(0xc0); // checkcast dos.writeShort(cp.lookupClass(wrNm)); dos.write(0xb6); // invokevirtual dos.writeShort(cp.lookupMethod(wrNm, info.valueMethod, "()" + info.typeDescriptor)); dos.write(info.returnInstruction); } else { dos.write(0xc0); // checkcast dos.writeShort(cp.lookupClass(ret.getName().replace('.', '/'))); dos.write(0xb0); // areturn } // csaito: for catched exceptions for (int j = 0; j < exceptions.length; j++) { dos.write(0x4c); // astore_1 dos.write(0x2b); // aload_1 dos.write(0xbf); // athrow } {// For RuntimeException dos.write(0x4c); // astore_1 dos.write(0x2b); // aload_1 dos.write(0xbf); // athrow } {// For General Exception dos.write(0x4c); // astore_1 dos.write(0xbb); // new dos.writeShort(cp.lookupClass("java/rmi/UnexpectedException")); dos.write(0x59); // dup dos.write(0x12); // lcd dos.write(cp.lookupStringConstant("")); // lcd dos.write(0x2b); // aload_1 dos.write(0xb7); // invokespecial dos.writeShort(cp.lookupMethod("java/rmi/UnexpectedException", "<init>", unexpectedExceptionDescriptor)); dos.write(0xbf); // athrow } // finally, a return. if (Void.TYPE.equals(ret)) { dos.write(0xb1); // return } // The rest of the code attribute: // First, the exception table. dos.writeShort(exceptions.length + 2);// exception_table_length int astore_start; if (Void.TYPE.equals(ret)) { astore_start = pc_end + 3; // after goto } else { astore_start = pc_end + 1; // after return } for (int j = exceptions.length-1; j >= 0; j--) { dos.writeShort(0); // pc_start dos.writeShort(pc_end); // pc_end dos.writeShort(astore_start); dos.writeShort(cp.lookupClass(exceptions[j].getName().replace('.', '/'))); astore_start += 3; } { // for RuntimeException dos.writeShort(0); // pc_start dos.writeShort(pc_end); // pc_end dos.writeShort(astore_start); dos.writeShort(cp.lookupClass("java/lang/RuntimeException")); astore_start += 3; } { // for general Exception dos.writeShort(0); // pc_start dos.writeShort(pc_end); // pc_end dos.writeShort(astore_start); dos.writeShort(cp.lookupClass("java/lang/Exception")); } dos.writeShort(0); // attribute_count // Now the second attribute of the method dos.writeShort(cp.lookupString("Exceptions")); dos.writeInt(4); dos.writeShort(1); dos.writeShort(cp.lookupClass("java/rmi/RemoteException")); } // Attributes (of ClassFile): dos.writeShort(0); // And we're done! dos.close(); // @@: uncomment below to write out the generated stub class /**** System.out.println("@@ dumping class " + stubName** + " to /tmp/foo.class file for debug");** try {** dos = new DataOutputStream(new java.io.FileOutputStream(** "/tmp/foo.class"));** dos.write(bos.toByteArray());** dos.close();** } catch (java.io.FileNotFoundException e) {** System.out.println("@@ cannot write " + stubName** + " to .class file to this file system");** } catch (SecurityException se) {** System.out.println("@@ cannot write " + stubName** + " to .class file to this file system");** }**/ return bos.toByteArray(); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -