{"id":20649931,"url":"https://github.com/micartey/jairo","last_synced_at":"2025-09-26T21:30:45.853Z","repository":{"id":51062199,"uuid":"324625011","full_name":"micartey/jairo","owner":"micartey","description":"Java Transformer Agent","archived":false,"fork":false,"pushed_at":"2025-01-15T00:00:16.000Z","size":658,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-01-15T01:21:12.505Z","etag":null,"topics":["asm","bytecode","injection","java","java-agent","javaagent","javaassist","transformer"],"latest_commit_sha":null,"homepage":"https://micartey.github.io/jairo/docs","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/micartey.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-12-26T19:52:42.000Z","updated_at":"2025-01-01T03:21:10.000Z","dependencies_parsed_at":"2025-01-01T04:19:13.911Z","dependency_job_id":"0db02005-370f-40f9-8049-01f0f506aaca","html_url":"https://github.com/micartey/jairo","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/micartey%2Fjairo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/micartey%2Fjairo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/micartey%2Fjairo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/micartey%2Fjairo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/micartey","download_url":"https://codeload.github.com/micartey/jairo/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":234346346,"owners_count":18817717,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["asm","bytecode","injection","java","java-agent","javaagent","javaassist","transformer"],"created_at":"2024-11-16T17:17:05.969Z","updated_at":"2025-09-26T21:30:45.425Z","avatar_url":"https://github.com/micartey.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# jairo\n\n\u003cdiv align=\"center\"\u003e\n  \u003ca href=\"https://www.oracle.com/java/\"\u003e\n    \u003cimg\n      src=\"https://img.shields.io/badge/Written%20in-java-%23EF4041?style=for-the-badge\"\n      height=\"30\"\n    /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://jitpack.io/#micartey/jairo/main-SNAPSHOT\"\u003e\n    \u003cimg\n      src=\"https://img.shields.io/badge/jitpack-main-%2321f21?style=for-the-badge\"\n      height=\"30\"\n    /\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://micartey.github.io/jairo/docs\" target=\"_blank\"\u003e\n    \u003cimg\n      src=\"https://img.shields.io/badge/javadoc-reference-5272B4.svg?style=for-the-badge\"\n      height=\"30\"\n    /\u003e\n  \u003c/a\u003e\n\u003c/div\u003e\n\n\u003cbr\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"#-introduction\"\u003eIntroduction\u003c/a\u003e |\n  \u003ca href=\"#-build-tools\"\u003eMaven/Gradle\u003c/a\u003e |\n  \u003c!-- \u003ca href=\"#-troubleshooting\"\u003eTroubleshooting\u003c/a\u003e | --\u003e\n  \u003ca href=\"#-getting-started\"\u003eGetting started\u003c/a\u003e\n\u003c/p\u003e\n\n## 📚 Introduction\n\njairo is a custom transformer which provides an easy way to change the method body of classes. The transformer will be used through the `Instrumentation` which is provided by java using the java agent. It heavily depends on the [javaassist](https://github.com/jboss-javassist/javassist) library to change the bytecode at runtime.\n\n### Motivation\n\nChanging code at runtime makes a lot of things easier. E.g. if you want to trigger an event after a class is created or a method is invoked whose implementation you have no control over. Maybe you wan't to benchmark a method etc... In such cases, it could be pleasent to just rewrite implementations at runtime without having to download, decompile, edit and recompile your dependencies.\n\n\n## 🔗 Build Tools\n\nTo use jairo as a dependency you might want to use a build tool like maven or gradle. An easy way for each and every project, is to use [jitpack](https://jitpack.io/#micartey/jairo/main-SNAPSHOT) as it makes it easy to implement and use. The following example is for maven specific, as I personally don't use gradle that much.\n\n### Maven\n\nFirst of all add a new repository to your `pom.xml` file to be able to download the dependecies provided by jitpack.\n\n```xml\n\u003crepositories\u003e\n    \u003crepository\u003e\n        \u003cid\u003ejitpack.io\u003c/id\u003e\n        \u003curl\u003ehttps://jitpack.io\u003c/url\u003e\n    \u003c/repository\u003e\n\u003c/repositories\u003e\n```\n\nLastly, after adding the repository to all your other repositories, you have to add the following segment to your dependencies.\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.github.micartey\u003c/groupId\u003e\n    \u003cartifactId\u003ejairo\u003c/artifactId\u003e\n    \u003cversion\u003emain-SNAPSHOT\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n## 🎈 Getting started\n\nA good way to get started, is to check out the [javadoc](https://micartey.github.io/jairo/docs) in order to get an overview of available annotations as they are the key in order to control the behavior. There are a total of [6 annotations](https://micartey.github.io/jairo/docs/me/micartey/jairo/annotation/package-summary.html) you have to know and use.\n\n\u003cdetails open\u003e\n\u003csummary\u003e Expand for an overview of available annotations \u003c/summary\u003e\n\u003cbr\u003e\n\n| Annotation | Description | Scope    | |\n|------------|-------------|----------|-|\n| [@Field](https://micartey.github.io/jairo/docs/me/micartey/jairo/annotation/Field.html)     | The `@Field` annotation is used to specify the parameter name at runtime. Make sure to avoid name collisions | Class |\n| [@Hook](https://micartey.github.io/jairo/docs/me/micartey/jairo/annotation/Hook.html) | The `@Hook` annotation specifies on which class the injection should be applied | Class |\n| [@Name](https://micartey.github.io/jairo/docs/me/micartey/jairo/annotation/Name.html) | The `@Name` annotation is used in case your method name deffers from the method you are trying to inject. | Method | optional |\n| [@Overwrite](https://micartey.github.io/jairo/docs/me/micartey/jairo/annotation/Overwrite.html) | The `@Overwrite` annotation specifies which type of injection should be used. You can choose between: \u003cul\u003e\u003cli\u003eBefore\u003c/li\u003e\u003cli\u003eAfter\u003c/li\u003e\u003cli\u003eReplace\u003c/li\u003e\u003c/ul\u003e | Method |\n| [@Parameter](https://micartey.github.io/jairo/docs/me/micartey/jairo/annotation/Parameter.html) | The `@Parameter` annotation is only used in case many methods in a class share the same name. While they can share the same name, they cannot share the same signature. By specifiying the method parameters of the target method, the right method can be injected | Method | optional |\n| [@Return](https://micartey.github.io/jairo/docs/me/micartey/jairo/annotation/Return.html) | The `@Return` annotation can only be used with `Overwrite.Type.Replace` and will replace the target methods content with a return statement | Method | optional |\n\n\u003c/details\u003e\n\n### Hook to a Class\n\nIn order to overwrite methods of a class, jairo needs to know on which classes it should apply (re-)transformations. This is being archived by the `@Hook` annotation as previously described.\n\n```java\npackage my.test.path;\n\npublic class Target {\n    ...\n}\n```\n\nLet's assume Target is the target class on which we want to perform some transformations. Now create another class which has the `@Hook` annotation:\n\n```java\npackage some.random.path;\n\n@Field(\"targetInjectorInstance\")\n@Hook(\"my.test.path.Target\")\npublic class TargetInjector {\n    ...\n}\n```\n\nAs you can see, the `@Field` annotations was also added. This annotation is very important as it specifies the instance name of the global variable which will be added in order to hold an instance of `TargetInjector` inside `Target`.\n\nThe following section illustrates what is happening to the `Target` class at runtime:\n\n```java\npackage my.test.path;\n\npublic class Target {\n    private TargetInjector targetInjectorInstance = new TargetInjector()\n    ...\n}\n```\n\n### Overwrite a method\n\nNext up is to overwrite a method. Let's assume that you have a method called `addNumbers` as follows:\n\n```java\npublic int addNumbers(int a, int b) {\n    return a + b;\n}\n```\n\nAnd we want to print both numbers out before the are being calculated for some reason.\n\n```java\n@Name(\"addNumber\")\n@Overwrite(Overwrite.Type.BEFORE)\npublic void printNumbersBeforeAdding(Object instance, int a, int b) {\n    System.out.println(String.format(\"a: %s b: %s\", a, b));\n}\n```\n\n\n## 💉 Injecting into a JVM\n\nThere are different ways to inject into a JVM. The best option is to specify a javaagent with the start-up command. This will ensure that the transformations will be applied, since classes don't have to be retransformed.\n\n### Command line\n\n```text\njava -javaagent:Agent.jar -jar MyApplication.jar\n```\n\n```text\nManifest-Version: 1.0\nPremain-Class: my.path.to.Agent\n```\n\n```java\npublic static void premain(String arguments, Instrumentation instrumentation) {\n    JairoTransformer transformer = new JairoTransformer(Daddy.class);\n    instrumentation.addTransformer(transformer);\n}\n```\n\n### Injection\n\n```text\nManifest-Version: 1.0\nAgent-Class: my.path.to.Agent\nCan-Redefine-Classes: true\nCan-Retransform-Classes: true\n```\n\n```java\npublic static void agentmain(String args, Instrumentation instrumentation) {\n    JairoTransformer transformer = new JairoTransformer(Daddy.class);\n    transformer.retransform(instrumentation);\n}\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmicartey%2Fjairo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmicartey%2Fjairo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmicartey%2Fjairo/lists"}