由于
GeneratorAdapterextendsLocalVariablesSorter的目的是适应所有访问者调用,因此与引入的专用方法不同,所有访问者API的方法都将得到适应GeneratorAdapter。这种设计允许将新代码插入到现有方法中,在旧方法中,旧代码通过访问者API报告。
因此
visitLocalVariable,作为访问者API一部分的方法必须MethodVisitor绕过目标在目标上调用
LocalVariablesSorter:
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_frameS);String name = "com.test.Sub";cw.visit(Oppres.V1_8, Oppres.ACC_PUBLIC, name.replace('.', '/'), null, "java/lang/Object", null);Method ctor = Method.getMethod("void <init>()");MethodVisitor direct = cw.visitMethod( Oppres.ACC_PUBLIC, ctor.getName(), ctor.getDescriptor(), null, null);GeneratorAdapter mg = new GeneratorAdapter(Oppres.ACC_PUBLIC, ctor, direct);mg.visitCode();mg.loadThis();mg.invokeConstructor(Type.getType(Object.class), ctor);int var = mg.newLocal(Type.DOUBLE_TYPE);mg.push(42.42);mg.storeLocal(var);Label varLabel = mg.mark();mg.returnValue();Label endLabel = mg.mark();direct.visitLocalVariable("x", "D", null, varLabel, endLabel, var);mg.endMethod();cw.visitEnd();byte[] bytes = cw.toByteArray();Files.write(Paths.get(name + ".class"), bytes);
由于这可能会造成混淆,因此,这里的替代方法MethodVisitor完全可以直接在目标上工作,而无需使用任何便利包装GeneratorAdapter。它并不复杂,尽管需要更多的知识,但是,它是开发人员在处理Java字节码和类文件时应该拥有的知识……
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_frameS);String name = "com.test.Sub";String superClName = "java/lang/Object", ctorName = "<init>", ctorDesc = "()V";cw.visit(Oppres.V1_8, Oppres.ACC_PUBLIC, name.replace('.','/'), null, superClName, null);MethodVisitor direct = cw.visitMethod(Oppres.ACC_PUBLIC, ctorName, ctorDesc, null, null);direct.visitCode();// "this" is alway 0 (zero) and for parameterless methods the next var location is 1 (one)int thisVar = 0, var = 1;direct.visitVarInsn(Oppres.ALOAD, thisVar);direct.visitMethodInsn(Oppres.INVOKESPECIAL, superClName, ctorName, ctorDesc, false);direct.visitLdcInsn(42.42);Label varLabel = new Label(), endLabel = new Label();direct.visitVarInsn(Oppres.DSTORE, var);direct.visitLabel(varLabel);direct.visitInsn(Oppres.RETURN);direct.visitLabel(endLabel);direct.visitLocalVariable("x", "D", null, varLabel, endLabel, var);direct.visitMaxs(-1, -1);// no actual values, using COMPUTE_frameSdirect.visitEnd();cw.visitEnd();byte[] bytes = cw.toByteArray();Files.write(Paths.get(name + ".class"), bytes);
如果您不满意直接使用()V无参数void方法,则仍可以Method像之前或之前那样使用对象Type.getMethodDescriptor(Type.VOID_TYPE)
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)