private static void inheritAnnotations(final CtClass theClass, final CtMethod theMethod) throws NotFoundException { if (hasMethod(theClass, theMethod)) { CtMethod aOtherMethod = theClass.getMethod(theMethod.getName(), theMethod.getSignature()); // method we're probably overriding or implementing in the case of an abstract method. AnnotationsAttribute annotationsAttribute = (AnnotationsAttribute) aOtherMethod.getMethodInfo().getAttribute(AnnotationsAttribute.visibleTag); if (annotationsAttribute != null) { ConstPool cp = theClass.getClassFile().getConstPool(); AnnotationsAttribute attr = new AnnotationsAttribute(cp, AnnotationsAttribute.visibleTag); for (Object obj : annotationsAttribute.getAnnotations()) { Annotation a = (Annotation) obj; Annotation theAnnotation = new Annotation(a.getTypeName(), cp); if (a.getMemberNames() != null) { for (Object aName : a.getMemberNames()) { theAnnotation.addMemberValue(aName.toString(), a.getMemberValue(aName.toString())); } } attr.setAnnotation(theAnnotation); } theMethod.getMethodInfo().addAttribute(attr); } } }
/** * Similar to main method but is not static * * @param args command line parameters * @throws Exception if something fails during the execution */ public void doIt2(String[] args) throws Exception { // Se carga la clase para la que se quiere modificar sus bytecodes ClassPool pool = ClassPool.getDefault(); CtClass cc = pool.get("com.jzb.ja.Clase1"); // Se puede iterar imprimiendo los metodos, y su signatura, contenidos en la clase for (CtMethod mm : cc.getMethods()) { System.out.println(mm.getName() + " " + mm.getMethodInfo().getDescriptor()); } // Se puede buscar un metodo en concreto... CtMethod mr = cc.getMethod("diHola", "(Ljava/lang/String;)Ljava/lang/String;"); // ... Borrarlo... cc.removeMethod(mr); // .. Y volver a escribir su .class moficado en una carpeta raiz cc.writeFile("c:\\tmp"); // Posteriormente, tanto por este codigo de creación dinamica, o porque se usa // el fichero .class generado antes, se obtiene un error de "Metodo No Existe" Class c1 = cc.toClass(); Clase1 o1 = (Clase1) c1.newInstance(); System.out.println(o1.sumaUno(2)); System.out.println(o1.diHola("Pepe")); }
/* 66: */ /* 67: */ private boolean matchClass(String name, ClassPool pool) /* 68: */ { /* 69: 84 */ if (this.classname.equals(name)) { /* 70: 85 */ return true; /* 71: */ } /* 72: */ try /* 73: */ { /* 74: 88 */ CtClass clazz = pool.get(name); /* 75: 89 */ CtClass declClazz = pool.get(this.classname); /* 76: 90 */ if (clazz.subtypeOf(declClazz)) { /* 77: */ try /* 78: */ { /* 79: 92 */ CtMethod m = clazz.getMethod(this.methodname, this.methodDescriptor); /* 80: 93 */ return m.getDeclaringClass().getName().equals(this.classname); /* 81: */ } /* 82: */ catch (NotFoundException e) /* 83: */ { /* 84: 97 */ return true; /* 85: */ } /* 86: */ } /* 87: */ } /* 88: */ catch (NotFoundException e) /* 89: */ { /* 90:101 */ return false; /* 91: */ } /* 92:104 */ return false; /* 93: */ }
private static boolean hasMethod(final CtClass theClass, final CtMethod theMethod) { try { return theClass.getMethod(theMethod.getName(), theMethod.getSignature()) != null; } catch (NotFoundException e) { return false; } }
@Test public void testSetter() throws Exception { CtClass mock = new WicketMockClassFactory(Date.class).getMock(); assertNotNull( mock.getMethod( "setSeconds", Descriptor.ofMethod( voidType, new CtClass[] {ClassPool.getDefault().get(Object.class.getName())}))); }
private void initExtraHarvest() { try { CtClass terraForming = HookManager.getInstance() .getClassPool() .get("com.wurmonline.server.behaviours.Terraforming"); CtClass[] paramTypes = { HookManager.getInstance().getClassPool().get("com.wurmonline.server.creatures.Creature"), CtPrimitiveType.intType, CtPrimitiveType.intType, CtPrimitiveType.booleanType, CtPrimitiveType.intType, CtPrimitiveType.floatType, HookManager.getInstance().getClassPool().get("com.wurmonline.server.items.Item") }; CtMethod method = terraForming.getMethod( "harvest", Descriptor.ofMethod(CtPrimitiveType.booleanType, paramTypes)); MethodInfo methodInfo = method.getMethodInfo(); CodeAttribute codeAttribute = methodInfo.getCodeAttribute(); CodeIterator codeIterator = codeAttribute.iterator(); LocalVariableAttribute attr = (LocalVariableAttribute) codeAttribute.getAttribute(LocalVariableAttribute.tag); int quantityIndex = -1; for (int i = 0; i < attr.tableLength(); i++) { if ("quantity".equals(attr.variableName(i))) { quantityIndex = attr.index(i); } } if (quantityIndex == -1) { throw new HookException("Quantity variable can not be resolved"); } while (codeIterator.hasNext()) { int pos = codeIterator.next(); int op = codeIterator.byteAt(pos); if (op == CodeIterator.ISTORE) { int fieldRefIdx = codeIterator.byteAt(pos + 1); if (quantityIndex == fieldRefIdx) { Bytecode bytecode = new Bytecode(codeIterator.get().getConstPool()); bytecode.addIconst(extraHarvest); bytecode.add(Bytecode.IADD); codeIterator.insertAt(pos, bytecode.get()); break; } } } } catch (NotFoundException | BadBytecode e) { throw new HookException(e); } }
@Override public void compile(HookCompiler compiler, CtClass c, Side side) throws NotFoundException, CannotCompileException { compiler.replaceDouble( c.getMethod("tick", "()V"), -64, EntryFactory.getClassEntry(getClass()), "getOutOfWorldDepth", "this"); }
@Test(expected = NotFoundException.class) public void testFinalField() throws Exception { CtClass mock = new WicketMockClassFactory(FieldContainer.class).getMock(); mock.getMethod("setField", Descriptor.ofMethod(voidType, new CtClass[] {intType})); }
@Test(expected = Test.None.class) public void testField() throws Exception { CtClass mock = new WicketMockClassFactory(FieldContainer.class).getMock(); mock.getMethod("getNonFinalField", Descriptor.ofMethod(OBJECT_CLASS, new CtClass[] {})); mock.getMethod("setNonFinalField", Descriptor.ofMethod(voidType, new CtClass[] {intType})); }
private URL computeResourceURL(Method method) throws NotFoundException, URISyntaxException { List<ResourceFileEntry> filesSimpleNames = new ArrayList<ResourceFileEntry>(); boolean computeExtensions = false; CtMethod m = ctClass.getMethod(method.getName(), getDescriptor(method)); MethodInfo minfo = m.getMethodInfo2(); AnnotationsAttribute attr = (AnnotationsAttribute) minfo.getAttribute(AnnotationsAttribute.invisibleTag); if (attr != null) { Annotation an = attr.getAnnotation(Source.class.getName()); if (an != null) { MemberValue[] mvArray = ((ArrayMemberValue) an.getMemberValue("value")).getValue(); if (mvArray != null) { for (MemberValue mv : mvArray) { StringMemberValue smv = (StringMemberValue) mv; filesSimpleNames.add(new ResourceFileEntry(smv.getValue(), m)); } } } } if (filesSimpleNames.isEmpty()) { // no @Source annotation detected filesSimpleNames.add(new ResourceFileEntry(method.getName(), m)); computeExtensions = true; } List<URL> existingFiles = new ArrayList<URL>(); for (ResourceFileEntry resourceEntry : filesSimpleNames) { String resourceName = resourceEntry.resourceName; CtClass declaringClass = resourceEntry.resourceMethod.getDeclaringClass(); String baseDir = declaringClass.getPackageName().replaceAll("\\.", "/") + "/"; String fileName = (resourceName.startsWith(baseDir)) ? resourceName : baseDir + resourceName; if (computeExtensions) { String[] extensions = getResourceDefaultExtensions(method); for (String extension : extensions) { String possibleFile = fileName + extension; URL url = GwtPatcher.class.getClassLoader().getResource(possibleFile); if (url != null) { existingFiles.add(url); } } } else { URL url = GwtPatcher.class.getClassLoader().getResource(fileName); if (url != null) { existingFiles.add(url); } } } if (existingFiles.isEmpty()) { throw new RuntimeException( "No resource file found for method " + ctClass.getSimpleName() + "." + method.getName() + "()"); } else if (existingFiles.size() > 1) { throw new RuntimeException( "Too many resource files found for method " + ctClass.getSimpleName() + "." + method.getName() + "()"); } return existingFiles.get(0); }
// @Deprecated // @Test public void interceptor() throws NotFoundException, CannotCompileException, IllegalAccessException, InstantiationException, IOException, ClassNotFoundException, NoSuchMethodException { AroundInterceptor aroundInterceptor = new AroundInterceptor() { @Override public void before(Object target, Object[] args) { logger.info("BEFORE target:" + target + " args:" + Arrays.toString(args)); } @Override public void after(Object target, Object[] args, Object result, Throwable throwable) { logger.info( "AFTER target: " + target + " args:" + Arrays.toString(args) + " result:" + result + " throwable:" + throwable); } }; int interceptorId = INTERCEPTOR_REGISTRY_ADAPTOR.addInterceptor(aroundInterceptor); final ClassPool classPool = new ClassPool(true); CtClass throwable = classPool.get(Throwable.class.getName()); CtClass ctClass = classPool.get("com.baidu.oped.apm.profiler.interceptor.JavaAssistTestObject"); final CtMethod hello = ctClass.getMethod("hello", "(Ljava/lang/String;)Ljava/lang/String;"); logger.debug("longName:{}", hello.getLongName()); logger.debug("name:{}", hello.getName()); String interceptorClassName = AroundInterceptor.class.getName(); CtClass interceptor = classPool.get(interceptorClassName); hello.addLocalVariable("interceptor", interceptor); CtClass object = classPool.get(Object.class.getName()); hello.addLocalVariable("result", object); // hello.insertBefore("{ System.out.println(\"BEFORE\"); }"); hello.insertBefore( "{" + "interceptor = (" + interceptorClassName + ") " + InterceptorRegistry.class.getName() + ".getSimpleInterceptor(" + interceptorId + ");" + "interceptor.before(this, $args);" + "}"); // hello.addCatch("{" + //// " interceptor.after(ctx);"+ //// " AroundInterceptor a = (AroundInterceptor) " + // InterceptorRegistry.class.getName() + ".getStaticInterceptor(\"a\");"+ // " throw $e;" + // "}", throwable); // hello.insertAfter("{" + // "interceptor.after(this, $args, ($w)$_, null); " + // "}"); // hello.setBody(generatedAroundInterceptor("TestObject", "hello")); // hello.setBody("{ System.out.println(\"ddd\"); }", ClassMap map ); // hello.insertBefore(" System.out.println(\" BEFORE + \");"); // hello.insertAfter(" System.out.println($_);"); // hello.insertAfter(" System.out.println($r);"); // hello.insertAfter(" System.out.println($w);"); // hello.insertAfter(" System.out.println($sig);"); // hello.insertAfter(" System.out.println($type);"); // hello.insertAfter(" System.out.println($class);"); // hello.instrument(new ExprEditor() { // public void edit(MethodCall m) // throws CannotCompileException // { // try { // System.out.println("method call" + m.getMethod().getName()); // } catch (NotFoundException e) { // e.printStackTrace(); //To change body of catch statement use File | Settings // | File Templates. // } // String code = generatedAroundInterceptor("TestObject", "hello"); // m.replace(code); // } // }); // hello.addCatch("System.out.println(\"catch\"); throw $e;", throwable); // hello.setName("__hello"); // CtMethod method = CtNewMethod.make("public void hello() { try {__hello(); } // catch(Throwable th){throw th;}}", ctClass); // CtMethod method = CtNewMethod.make("public void hello() { // System.out.println(\"ddd\"); } catch(Throwable th){throw th;}}", ctClass); // ctClass.addMethod(method); // ctClass.freeze(); // ctClass.writeFile("./debug"); // ctClass.debugWriteFile("./debug"); Loader loader = LoaderUtils.createLoader(classPool); loader.delegateLoadingOf("com.baidu.oped.apm.bootstrap."); Class aClass = loader.loadClass(ctClass.getName()); Object testObject = aClass.newInstance(); Method helloMethod = testObject.getClass().getDeclaredMethod("hello", String.class); try { helloMethod.invoke(testObject, "hello~~"); } catch (Exception e) { Assert.fail(e.getMessage()); } // o.hello(); }
/** Generate Javassist Proxy Classes */ private static <T> void generateProxyClass( Class<T> primaryInterface, String superClassName, String methodBody) throws Exception { String newClassName = superClassName.replaceAll("(.+)\\.(\\w+)", "$1.Hikari$2"); CtClass superCt = classPool.getCtClass(superClassName); CtClass targetCt = classPool.makeClass(newClassName, superCt); targetCt.setModifiers(Modifier.FINAL); System.out.println("Generating " + newClassName); targetCt.setModifiers(Modifier.PUBLIC); // Make a set of method signatures we inherit implementation for, so we don't generate delegates // for these Set<String> superSigs = new HashSet<>(); for (CtMethod method : superCt.getMethods()) { if ((method.getModifiers() & Modifier.FINAL) == Modifier.FINAL) { superSigs.add(method.getName() + method.getSignature()); } } Set<String> methods = new HashSet<>(); Set<Class<?>> interfaces = getAllInterfaces(primaryInterface); for (Class<?> intf : interfaces) { CtClass intfCt = classPool.getCtClass(intf.getName()); targetCt.addInterface(intfCt); for (CtMethod intfMethod : intfCt.getDeclaredMethods()) { final String signature = intfMethod.getName() + intfMethod.getSignature(); // don't generate delegates for methods we override if (superSigs.contains(signature)) { continue; } // Ignore already added methods that come from other interfaces if (methods.contains(signature)) { continue; } // Ignore default methods (only for Jre8 or later) if (isDefaultMethod(intf, intfCt, intfMethod)) { continue; } // Track what methods we've added methods.add(signature); // Clone the method we want to inject into CtMethod method = CtNewMethod.copy(intfMethod, targetCt, null); String modifiedBody = methodBody; // If the super-Proxy has concrete methods (non-abstract), transform the call into a simple // super.method() call CtMethod superMethod = superCt.getMethod(intfMethod.getName(), intfMethod.getSignature()); if ((superMethod.getModifiers() & Modifier.ABSTRACT) != Modifier.ABSTRACT) { modifiedBody = modifiedBody.replace("((cast) ", ""); modifiedBody = modifiedBody.replace("delegate", "super"); modifiedBody = modifiedBody.replace("super)", "super"); } modifiedBody = modifiedBody.replace("cast", primaryInterface.getName()); // Generate a method that simply invokes the same method on the delegate if (isThrowsSqlException(intfMethod)) { modifiedBody = modifiedBody.replace("method", method.getName()); } else { modifiedBody = "{ return ((cast) delegate).method($$); }" .replace("method", method.getName()) .replace("cast", primaryInterface.getName()); } if (method.getReturnType() == CtClass.voidType) { modifiedBody = modifiedBody.replace("return", ""); } method.setBody(modifiedBody); targetCt.addMethod(method); } } targetCt.writeFile("target/classes"); }