{"id":19430420,"url":"https://github.com/minimallycorrect/javatransformer","last_synced_at":"2025-10-14T03:27:22.561Z","repository":{"id":37502353,"uuid":"49785717","full_name":"MinimallyCorrect/JavaTransformer","owner":"MinimallyCorrect","description":"Applies transformations to .java and .class files","archived":false,"fork":false,"pushed_at":"2025-10-04T20:37:46.000Z","size":753,"stargazers_count":11,"open_issues_count":17,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-14T03:27:20.228Z","etag":null,"topics":["java","java-bytecode","java-source","java-transformation"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MinimallyCorrect.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,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["LunNova"]}},"created_at":"2016-01-16T18:34:51.000Z","updated_at":"2024-09-07T23:09:16.000Z","dependencies_parsed_at":"2024-01-01T17:30:54.302Z","dependency_job_id":"f1f5b574-cfd9-4e2a-b90d-3da5a0449600","html_url":"https://github.com/MinimallyCorrect/JavaTransformer","commit_stats":null,"previous_names":[],"tags_count":53,"template":false,"template_full_name":null,"purl":"pkg:github/MinimallyCorrect/JavaTransformer","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MinimallyCorrect%2FJavaTransformer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MinimallyCorrect%2FJavaTransformer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MinimallyCorrect%2FJavaTransformer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MinimallyCorrect%2FJavaTransformer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MinimallyCorrect","download_url":"https://codeload.github.com/MinimallyCorrect/JavaTransformer/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MinimallyCorrect%2FJavaTransformer/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279017766,"owners_count":26086144,"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","status":"online","status_checked_at":"2025-10-14T02:00:06.444Z","response_time":60,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["java","java-bytecode","java-source","java-transformation"],"created_at":"2024-11-10T14:24:52.707Z","updated_at":"2025-10-14T03:27:22.531Z","avatar_url":"https://github.com/MinimallyCorrect.png","language":"Java","funding_links":["https://github.com/sponsors/LunNova"],"categories":[],"sub_categories":[],"readme":"JavaTransformer\n====\n\u003c!---freshmark shields\noutput = [\n\tlink(image('Release notes', 'https://img.shields.io/maven-metadata/v?label=changelog\u0026metadataUrl=https%3A%2F%2Fjcenter.bintray.com%2F' + '{{group}}'.replaceAll(\"\\\\.\", \"%2F\") + '%2F{{name}}%2Fmaven-metadata.xml'), '{{releaseNotesPath}}'),\n\tlink(shield('Maven artifact', 'jcenter', '{{name}}', 'blue'), 'https://bintray.com/{{bintrayrepo}}/{{name}}/view'),\n\tlink(image('License', 'https://img.shields.io/github/license/{{organisation}}/{{name}}.svg'), 'LICENSE') + '  ',\n\tlink(image('Travis CI', 'https://travis-ci.org/{{organisation}}/{{name}}.svg'), 'https://travis-ci.org/{{organisation}}/{{name}}'),\n\tlink(image('Coverage', 'https://img.shields.io/codecov/c/github/{{organisation}}/{{name}}.svg'), 'https://codecov.io/gh/{{organisation}}/{{name}}/') + '  ',\n\tlink(image('Discord chat', 'https://img.shields.io/discord/{{discordId}}?logo=discord'), '{{discordInvite}}'),\n\t].join('\\n');\n--\u003e\n[![Release notes](https://img.shields.io/maven-metadata/v?label=changelog\u0026metadataUrl=https%3A%2F%2Fjcenter.bintray.com%2Forg%2Fminimallycorrect%2Fjavatransformer%2FJavaTransformer%2Fmaven-metadata.xml)](docs/release-notes.md)\n[![Maven artifact](https://img.shields.io/badge/jcenter-JavaTransformer-blue.svg)](https://bintray.com/minimallycorrect/minimallycorrectmaven/JavaTransformer/view)\n[![License](https://img.shields.io/github/license/MinimallyCorrect/JavaTransformer.svg)](LICENSE)  \n[![Travis CI](https://travis-ci.org/MinimallyCorrect/JavaTransformer.svg)](https://travis-ci.org/MinimallyCorrect/JavaTransformer)\n[![Coverage](https://img.shields.io/codecov/c/github/MinimallyCorrect/JavaTransformer.svg)](https://codecov.io/gh/MinimallyCorrect/JavaTransformer/)  \n[![Discord chat](https://img.shields.io/discord/313371711632441344?logo=discord)](https://discord.gg/YrV3bDm)\n\u003c!---freshmark /shields --\u003e\n\nApplies transformations to .java and .class files using a unified high level API.\n\n# Internal Architecture and Implementation\n\n## Project Structure\n\nJavaTransformer is organized into several key packages:\n\n- [`dev.minco.javatransformer.api`](src/main/java/dev/minco/javatransformer/api): Public API interfaces and classes\n- [`dev.minco.javatransformer.internal`](src/main/java/dev/minco/javatransformer/internal): Internal implementation details\n- [`dev.minco.javatransformer.internal.asm`](src/main/java/dev/minco/javatransformer/internal/asm): ASM-specific utilities and implementations\n- [`dev.minco.javatransformer.internal.util`](src/main/java/dev/minco/javatransformer/internal/util): General utility classes\n\n## Key Concepts\n\n- **Unified Abstraction**: The project provides a unified interface ([`ClassInfo`](src/main/java/dev/minco/javatransformer/api/ClassInfo.java), [`MethodInfo`](src/main/java/dev/minco/javatransformer/api/MethodInfo.java), [`FieldInfo`](src/main/java/dev/minco/javatransformer/api/FieldInfo.java)) for working with both bytecode and source code, allowing transformers to be written agnostic of the underlying format.\n\n- **Multi-format Support**: JavaTransformer can load, transform, and save both bytecode (.class) and source code (.java) files, seamlessly switching between formats as needed.\n\n- **Flexible Transformation**: The transformer system allows for both general transformers (applied to all classes) and targeted transformers (applied to specific classes), providing fine-grained control over the transformation process.\n\n- **Code Fragment Insertion**: The [`CodeFragment`](src/main/java/dev/minco/javatransformer/api/code/CodeFragment.java) system allows for inserting new code into existing methods, supporting both bytecode and source code formats. This enables complex transformations that go beyond simple structural changes.\n\n- **Type Resolution**: The [`ResolutionContext`](src/main/java/dev/minco/javatransformer/internal/ResolutionContext.java) and [`ClassPath`](src/main/java/dev/minco/javatransformer/api/ClassPath.java) components provide robust type resolution capabilities, ensuring that transformations can accurately work with types across different classes and packages.\n\n- **Bytecode Generation**: For bytecode transformations, JavaTransformer uses ASM to generate and modify bytecode, providing low-level control over the JVM instructions.\n\n- **Source Code Generation**: For source code transformations, JavaTransformer uses JavaParser to generate and modify Java source code, preserving formatting and comments where possible.\n\n## Core Components and Their Interactions\n\n### JavaTransformer\n\nThe `JavaTransformer` class (`src/main/java/dev/minco/javatransformer/api/JavaTransformer.java`) serves as the main entry point for the transformation process. It orchestrates the loading, transformation, and saving of Java classes and source files.\n\nKey implementation details:\n- Maintains lists of general and targeted transformers\n- Uses a `ClassPath` object for type resolution\n- Implements separate logic for handling JAR files and folders\n- Delegates actual transformation to `ClassInfo` implementations\n\n### ClassInfo Hierarchy\n\nThe `ClassInfo` interface provides a unified abstraction for both bytecode and source code representations of Java classes.\n\n#### ByteCodeInfo\n\n`ByteCodeInfo` represents classes loaded from bytecode (.class files).\n\nImplementation details:\n- Uses ASM's `ClassNode` as the underlying representation (see [ASM ClassNode documentation](https://asm.ow2.io/javadoc/org/objectweb/asm/tree/ClassNode.html))\n- Lazily parses bytecode using [`AsmUtil.getClassNode()`](src/main/java/dev/minco/javatransformer/internal/asm/AsmUtil.java)\n- Implements [`MethodInfo`](src/main/java/dev/minco/javatransformer/api/MethodInfo.java) and [`FieldInfo`](src/main/java/dev/minco/javatransformer/api/FieldInfo.java) using ASM's [`MethodNode`](https://asm.ow2.io/javadoc/org/objectweb/asm/tree/MethodNode.html) and [`FieldNode`](https://asm.ow2.io/javadoc/org/objectweb/asm/tree/FieldNode.html)\n\n#### SourceInfo\n\n`SourceInfo` represents classes loaded from source code (.java files) using [JavaParser](https://javaparser.org/).\n\nImplementation details:\n- Uses JavaParser's [`TypeDeclaration`](https://www.javadoc.io/doc/com.github.javaparser/javaparser-core/latest/com/github/javaparser/ast/body/TypeDeclaration.html) as the underlying representation\n- Parses source code using JavaParser's [`StaticJavaParser`](https://www.javadoc.io/doc/com.github.javaparser/javaparser-core/latest/com/github/javaparser/StaticJavaParser.html)\n- Implements [`MethodInfo`](src/main/java/dev/minco/javatransformer/api/MethodInfo.java) and [`FieldInfo`](src/main/java/dev/minco/javatransformer/api/FieldInfo.java) using JavaParser's [`MethodDeclaration`](https://www.javadoc.io/doc/com.github.javaparser/javaparser-core/latest/com/github/javaparser/ast/body/MethodDeclaration.html) and [`FieldDeclaration`](https://www.javadoc.io/doc/com.github.javaparser/javaparser-core/latest/com/github/javaparser/ast/body/FieldDeclaration.html)\n\n### Transformation Process\n\n1. **Loading**: \n   - JAR files are processed using `ZipInputStream`\n   - Folders are traversed using `Files.walkFileTree()`\n   - Files are categorized as bytecode, source code, or other based on file extension\n\n2. **Parsing**:\n   - Bytecode: ASM's `ClassReader` is used to create a `ClassNode`\n   - Source code: JavaParser is used to create a `CompilationUnit` and extract `TypeDeclaration`s\n\n3. **Abstraction**:\n   - `ByteCodeInfo` or `SourceInfo` objects are created, wrapping the parsed data\n   - These objects implement the `ClassInfo` interface, providing a unified API\n\n4. **Transformation**:\n   - General transformers are applied to all `ClassInfo` objects\n   - Targeted transformers are applied to specific classes based on name matching\n   - Transformers modify the `ClassInfo`, `MethodInfo`, and `FieldInfo` objects\n\n5. **Code Generation**:\n   - Bytecode: Modified `ClassNode` objects are written using ASM's `ClassWriter`\n   - Source code: Modified AST nodes are converted back to source code using JavaParser's pretty-printing capabilities\n\n6. **Saving**:\n   - Transformed classes are written back to JAR files or folders\n   - The original file structure is preserved\n\n## CodeFragment System\n\nThe `CodeFragment` interface represents a piece of code that can be inserted into a method, supporting both bytecode and source code formats.\n\n### ByteCodeFragment\n\nRepresents bytecode instructions.\n\nImplementation details:\n- Stores a list of ASM `AbstractInsnNode` objects\n- Can be created from raw bytecode instructions or higher-level representations\n\n### SourceCodeFragment\n\nRepresents source code snippets.\n\nImplementation details:\n- Stores JavaParser `Statement` or `Expression` objects\n- Can be created from string literals or pre-parsed AST nodes\n\n### CodeFragmentGenerator\n\nThe `CodeFragmentGenerator` interface provides methods to generate `CodeFragment` objects from various input formats.\n\n#### AsmCodeFragmentGenerator\n\nGenerates `ByteCodeFragment` objects.\n\nImplementation details:\n- Uses ASM to parse and generate bytecode instructions\n- Handles conversion between high-level code representations and low-level bytecode\n\n#### SourceCodeFragmentGenerator\n\nGenerates `SourceCodeFragment` objects.\n\nImplementation details:\n- Uses JavaParser to parse source code snippets into AST nodes\n- Handles conversion between string literals and structured AST representations\n\n## Type Resolution and Context\n\n### ResolutionContext\n\nThe `ResolutionContext` class provides context for resolving types and members within a class or method.\n\nImplementation details:\n- Manages imports, type parameters, and scoping information\n- Uses the `ClassPath` to resolve external types\n- Implements separate resolution logic for bytecode and source code contexts\n\n### ClassPath\n\nThe `ClassPath` class represents the classpath used for resolving types during transformation.\n\nImplementation details:\n- Supports both file system and in-memory class loading\n- Caches resolved classes for performance\n- Handles resolution of array types and primitives\n\n## Utility Classes\n\n### AsmUtil\n\nProvides utility methods for working with ASM.\n\nKey functionalities:\n- Reading and writing class files\n- Converting between ASM and JavaTransformer type representations\n- Generating bytecode for common operations (e.g., method calls, field access)\n\n### JavaParserUtil\n\nProvides utility methods for working with JavaParser.\n\nKey functionalities:\n- Parsing and manipulating Java source code\n- Converting between JavaParser and JavaTransformer type representations\n- Generating AST nodes for common operations\n\n### JVMUtil\n\nProvides utility methods for working with JVM-related concepts.\n\nKey functionalities:\n- Converting between class names and file names\n- Handling JVM type descriptors and signatures\n\n## Class Loading and Resolution\n\nJavaTransformer employs a sophisticated class loading and resolution system to support its transformation capabilities:\n\n1. **ClassPath Hierarchy**: The `ClassPath` interface and its implementations (`FileClassPath`) provide a flexible way to represent and search for classes across multiple sources, including the system classpath, JARs, and directories.\n\n2. **Lazy Initialization**: The `FileClassPath` uses lazy initialization to load classes only when needed, improving performance for large classpaths.\n\n3. **Multiple Formats**: JavaTransformer can load and process both `.class` (bytecode) and `.java` (source code) files, providing a unified `ClassInfo` representation for both.\n\n4. **Resolution Context**: The `ResolutionContext` class plays a crucial role in resolving types, methods, and fields within the context of a specific class or method. This context-aware resolution is essential for accurate transformations, especially when dealing with complex type hierarchies or generic types.\n\n5. **Type Parameter Resolution**: JavaTransformer includes logic for resolving generic type parameters, as seen in the `Expressions` class, allowing it to handle complex generic scenarios in both bytecode and source code transformations.\n\nThese class loading and resolution capabilities enable JavaTransformer to perform accurate and context-aware transformations across a wide range of Java code structures and formats.\n\n## Forward Compatibility and JDK Version Support\n\nJavaTransformer aims to maintain compatibility with future JDK versions through several mechanisms:\n\n1. **Fallback to Reflection**: As noted in the [`ClassPaths`](src/main/java/dev/minco/javatransformer/internal/ClassPaths.java) class, there's a planned feature to fall back to reflection if [ASM](https://asm.ow2.io/) cannot load JDK classes:\n\n   ```java\n   // TODO: self-test, if we can't load JDK classes with current asm version fall back to reflection\n   ```\n\n   This fallback mechanism would allow JavaTransformer to understand the structure of JDK classes for use in [`ResolutionContext`](src/main/java/dev/minco/javatransformer/internal/ResolutionContext.java), even if it cannot modify them directly. While this limits the ability to transform these classes, it ensures that type resolution and other critical functionalities remain operational.\n\n2. **Modular JDK Support**: The `SystemClassPath` implementation already includes support for the modular JDK structure introduced in Java 9:\n\n   ```java\n   val fs = FileSystems.getFileSystem(URI.create(\"jrt:/\"));\n   return new FileClassPath(null, Collections.singletonList(fs.getPath(\"modules/java.base/\")));\n   ```\n\n   This allows JavaTransformer to work with both traditional and modular JDK structures.\n\n3. **Abstract Representations**: By using abstract representations like `ClassInfo`, `MethodInfo`, and `FieldInfo`, JavaTransformer can potentially adapt to changes in underlying class file formats without requiring extensive modifications to the core API.\n\nWhile these mechanisms provide a degree of forward compatibility, users should be aware that full support for new JDK features may require updates to JavaTransformer, particularly for transformations involving new language constructs or bytecode instructions.\n\n## Extension Points for Contributors\n\nTo extend or customize JavaTransformer, consider the following areas:\n\n1. **Custom Transformers**: Implement the `Transformer` interface to create new transformation logic.\n\n2. **New CodeFragment Types**: Extend `CodeFragment` to support new ways of representing and inserting code.\n\n3. **Additional File Formats**: Extend the loading and saving logic in `JavaTransformer` to support new file formats beyond JAR and folders.\n\n4. **Enhanced Type Resolution**: Extend `ResolutionContext` or `ClassPath` to improve type resolution capabilities, especially for complex scenarios involving generics or lambda expressions.\n\n5. **Optimization Passes**: Implement transformers that perform bytecode or source code optimizations.\n\n6. **Integration with Other Tools**: Create adapters or wrappers to integrate JavaTransformer with other bytecode or source code manipulation tools.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fminimallycorrect%2Fjavatransformer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fminimallycorrect%2Fjavatransformer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fminimallycorrect%2Fjavatransformer/lists"}