📄 proxymaker.java
字号:
code.pool.Class("java/lang/ClassNotFoundException")); */ int tojava = code.pool.Methodref( "org/python/core/Py", "tojava", "(" + $pyObj + $clss + ")" + $obj); code.invokestatic(tojava); // I guess I need this checkcast to keep the verifier happy code.checkcast(code.pool.Class(mapClass(ret))); break; } if (exceptions.length > 0) end.setPosition(); doReturn(code, ret); if (exceptions.length > 0) { boolean throwableFound = false; Label handlerStart = null; for (int i = 0; i < exceptions.length; i++) { handlerStart = code.getLabel(); handlerStart.setPosition(); code.stack = 1; int excLocal = code.getLocal("java/lang/Throwable"); code.astore(excLocal); code.aload(excLocal); code.athrow(); code.addExceptionHandler(start, end, handlerStart, code.pool.Class(mapClass(exceptions[i]))); doNullReturn(code, ret); code.freeLocal(excLocal); if (exceptions[i] == Throwable.class) throwableFound = true; } if (!throwableFound) { // The final catch (Throwable) handlerStart = code.getLabel(); handlerStart.setPosition(); code.stack = 1; int excLocal = code.getLocal("java/lang/Throwable"); code.astore(excLocal); code.aload(instLocal); code.aload(excLocal); int jthrow = code.pool.Methodref( "org/python/core/PyObject", "_jthrow", "(" + $throwable + ")V"); code.invokevirtual(jthrow); code.addExceptionHandler(start, end, handlerStart, code.pool.Class("java/lang/Throwable")); code.freeLocal(excLocal); doNullReturn(code, ret); } code.freeLocal(instLocal); } } public void addMethod(Method method, int access) throws Exception { boolean isAbstract = false; if (Modifier.isAbstract(access)) { access = access & ~Modifier.ABSTRACT; isAbstract = true; } Class[] parameters = method.getParameterTypes(); Class ret = method.getReturnType(); String sig = makeSignature(parameters, ret); String name = method.getName();// System.out.println(name+": "+sig); names.put(name, name); Code code = classfile.addMethod(name, sig, access); code.aload(0); code.ldc(name); if (!isAbstract) { int tmp = code.getLocal("org/python/core/PyObject"); int jfindattr = code.pool.Methodref( "org/python/core/Py", "jfindattr", "(" + $pyProxy + $str + ")" + $pyObj); code.invokestatic(jfindattr); code.astore(tmp); code.aload(tmp); Label callPython = code.getLabel(); code.ifnonnull(callPython); String superclass = mapClass(method.getDeclaringClass()); callSuper(code, name, superclass, parameters, ret, sig); callPython.setPosition(); code.aload(tmp); callMethod(code, name, parameters, ret, method.getExceptionTypes()); addSuperMethod("super__"+name, name, superclass, parameters, ret, sig, access); } else { if (!isAdapter) { int jgetattr = code.pool.Methodref( "org/python/core/Py", "jgetattr", "(" + $pyProxy + $str + ")" + $pyObj); code.invokestatic(jgetattr); callMethod(code, name, parameters, ret, method.getExceptionTypes()); } else { int jfindattr = code.pool.Methodref( "org/python/core/Py", "jfindattr", "(" + $pyProxy + $str + ")" + $pyObj); code.invokestatic(jfindattr); code.dup(); Label returnNull = code.getLabel(); code.ifnull(returnNull); callMethod(code, name, parameters, ret, method.getExceptionTypes()); returnNull.setPosition(); code.pop(); doNullReturn(code, ret); } } } private String methodString(Method m) { StringBuffer buf = new StringBuffer(m.getName()); buf.append(":"); Class[] params = m.getParameterTypes(); for (int i=0; i<params.length; i++) { buf.append(params[i].getName()); buf.append(","); } return buf.toString(); } protected void addMethods(Class c, Hashtable t) throws Exception { Method[] methods = c.getDeclaredMethods(); for (int i=0; i<methods.length; i++) { Method method = methods[i]; String s = methodString(method); if (t.containsKey(s)) continue; t.put(s, s); int access = method.getModifiers(); if (Modifier.isStatic(access) || Modifier.isPrivate(access)) { continue; } if (Modifier.isNative(access)) { access = access & ~Modifier.NATIVE; } if (Modifier.isProtected(access)) { access = (access & ~Modifier.PROTECTED) | Modifier.PUBLIC; if (Modifier.isFinal(access)) { addSuperMethod(methods[i], access); continue; } } else if (Modifier.isFinal(access)) { continue; } addMethod(methods[i], access); } Class sc = c.getSuperclass(); if (sc != null) addMethods(sc, t); Class[] interfaces = c.getInterfaces(); for (int j=0; j<interfaces.length; j++) { addMethods(interfaces[j], t); } } public void addConstructor(String name, Class[] parameters, Class ret, String sig, int access) throws Exception { Code code = classfile.addMethod("<init>", sig, access); callSuper(code, "<init>", name, parameters, Void.TYPE, sig); } public void addConstructors(Class c) throws Exception { Constructor[] constructors = c.getDeclaredConstructors(); String name = mapClass(c); for (int i=0; i<constructors.length; i++) { int access = constructors[i].getModifiers(); if (Modifier.isPrivate(access)) continue; if (Modifier.isNative(access)) access = access & ~Modifier.NATIVE; if (Modifier.isProtected(access)) access = access & ~Modifier.PROTECTED | Modifier.PUBLIC; Class[] parameters = constructors[i].getParameterTypes(); String sig = makeSignature(parameters, Void.TYPE); addConstructor(name, parameters, Void.TYPE, sig, access); } } // Super methods are added for the following three reasons: // // 1) for a protected non-final method add a public method with no // super__ prefix. This gives needed access to this method for // subclasses // // 2) for protected final methods, add a public method with the // super__ prefix. This avoids the danger of trying to override a // final method // // 3) For any other method that is overriden, add a method with the // super__ prefix. This gives access to super. version or the // method. // public void addSuperMethod(Method method, int access) throws Exception { Class[] parameters = method.getParameterTypes(); Class ret = method.getReturnType(); String sig = makeSignature(parameters, ret); String superclass = mapClass(method.getDeclaringClass()); String superName = method.getName(); String methodName = superName; if (Modifier.isFinal(access)) { methodName = "super__"+superName; access &= ~Modifier.FINAL; } addSuperMethod(methodName, superName, superclass, parameters, ret, sig, access); } public void addSuperMethod(String methodName, String superName, String declClass, Class[] parameters, Class ret, String sig, int access) throws Exception { if (methodName.startsWith("super__")) { /* rationale: JC java-class, P proxy-class subclassing JC in order to avoid infinite recursion P should define super__foo only if no class between P and JC in the hierarchy defines it yet; this means that the python class needing P is the first that redefines the JC method foo. */ try { superclass.getMethod(methodName,parameters); return; } catch(NoSuchMethodException e) { } catch(SecurityException e) { return; } } supernames.put(methodName, methodName); Code code = classfile.addMethod(methodName, sig, access); callSuper(code, superName, declClass, parameters, ret, sig); } public void addProxy() throws Exception { // implement PyProxy interface classfile.addField("__proxy", "Lorg/python/core/PyInstance;", Modifier.PROTECTED); // setProxy method Code code = classfile.addMethod("_setPyInstance", "(Lorg/python/core/PyInstance;)V", Modifier.PUBLIC); int field = code.pool.Fieldref(classfile.name, "__proxy", "Lorg/python/core/PyInstance;"); code.aload(0); code.aload(1); code.putfield(field); code.return_(); // getProxy method code = classfile.addMethod("_getPyInstance", "()Lorg/python/core/PyInstance;", Modifier.PUBLIC); code.aload(0); code.getfield(field); code.areturn(); // implement PyProxy interface classfile.addField("__systemState", "Lorg/python/core/PySystemState;", Modifier.PROTECTED | Modifier.TRANSIENT); // setProxy method code = classfile.addMethod("_setPySystemState", "(Lorg/python/core/PySystemState;)V", Modifier.PUBLIC); field = code.pool.Fieldref(classfile.name, "__systemState", "Lorg/python/core/PySystemState;"); code.aload(0); code.aload(1); code.putfield(field); code.return_(); // getProxy method code = classfile.addMethod("_getPySystemState", "()Lorg/python/core/PySystemState;", Modifier.PUBLIC); code.aload(0); code.getfield(field); code.areturn(); } public void addClassDictInit() throws Exception { int n = supernames.size(); // classDictInit method classfile.addInterface(mapClass(org.python.core.ClassDictInit.class)); Code code = classfile.addMethod("classDictInit", "(" + $pyObj + ")V", Modifier.PUBLIC | Modifier.STATIC); code.aload(0); code.ldc("__supernames__"); String[] names = new String[n]; Enumeration e = supernames.keys(); for (int i = 0; e.hasMoreElements(); ) names[i++] = (String) e.nextElement(); CodeCompiler.makeStrings(code, names, n); int j2py = code.pool.Methodref( "org/python/core/Py", "java2py", "(" + $obj + ")" + $pyObj); code.invokestatic(j2py); int setitem = code.pool.Methodref( "org/python/core/PyObject", "__setitem__", "(" + $str + $pyObj + ")V"); code.invokevirtual(setitem); code.return_(); } public void build() throws Exception { names = new Hashtable(); int access = superclass.getModifiers(); if ((access & Modifier.FINAL) != 0) { throw new InstantiationException("can't subclass final class"); } access = Modifier.PUBLIC | Modifier.SYNCHRONIZED; classfile = new ClassFile(myClass, mapClass(superclass), access); addProxy(); addConstructors(superclass); classfile.addInterface("org/python/core/PyProxy"); Hashtable seenmethods = new Hashtable(); for (int i=0; i<interfaces.length; i++) { if (interfaces[i].isAssignableFrom(superclass)) { Py.writeWarning("compiler", "discarding redundant interface: "+ interfaces[i].getName()); continue; } classfile.addInterface(mapClass(interfaces[i])); addMethods(interfaces[i], seenmethods); } addMethods(superclass, seenmethods); doConstants(); addClassDictInit(); } public static String makeProxy(Class superclass, OutputStream ostream) throws Exception { ProxyMaker pm = new ProxyMaker(superclass.getName(), superclass); pm.build(); pm.classfile.write(ostream); return pm.myClass; } public static File makeFilename(String name, File dir) { int index = name.indexOf("."); if (index == -1) return new File(dir, name+".class"); return makeFilename(name.substring(index+1, name.length()), new File(dir, name.substring(0, index))); } // This is not general enough public static OutputStream getFile(String d, String name) throws IOException { File dir = new File(d); File file = makeFilename(name, dir); new File(file.getParent()).mkdirs(); //System.out.println("proxy file: "+file); return new FileOutputStream(file); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -