Skip to content

Commit 8d536c8

Browse files
committed
README: document structure and some plans
1 parent 46f9506 commit 8d536c8

File tree

1 file changed

+234
-0
lines changed

1 file changed

+234
-0
lines changed

README.md

Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,237 @@ output = [
2121
<!---freshmark /shields -->
2222

2323
Applies transformations to .java and .class files using a unified high level API.
24+
25+
# Internal Architecture and Implementation
26+
27+
## Project Structure
28+
29+
JavaTransformer is organized into several key packages:
30+
31+
- [`dev.minco.javatransformer.api`](src/main/java/dev/minco/javatransformer/api): Public API interfaces and classes
32+
- [`dev.minco.javatransformer.internal`](src/main/java/dev/minco/javatransformer/internal): Internal implementation details
33+
- [`dev.minco.javatransformer.internal.asm`](src/main/java/dev/minco/javatransformer/internal/asm): ASM-specific utilities and implementations
34+
- [`dev.minco.javatransformer.internal.util`](src/main/java/dev/minco/javatransformer/internal/util): General utility classes
35+
36+
## Key Concepts
37+
38+
- **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.
39+
40+
- **Multi-format Support**: JavaTransformer can load, transform, and save both bytecode (.class) and source code (.java) files, seamlessly switching between formats as needed.
41+
42+
- **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.
43+
44+
- **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.
45+
46+
- **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.
47+
48+
- **Bytecode Generation**: For bytecode transformations, JavaTransformer uses ASM to generate and modify bytecode, providing low-level control over the JVM instructions.
49+
50+
- **Source Code Generation**: For source code transformations, JavaTransformer uses JavaParser to generate and modify Java source code, preserving formatting and comments where possible.
51+
52+
## Core Components and Their Interactions
53+
54+
### JavaTransformer
55+
56+
The `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.
57+
58+
Key implementation details:
59+
- Maintains lists of general and targeted transformers
60+
- Uses a `ClassPath` object for type resolution
61+
- Implements separate logic for handling JAR files and folders
62+
- Delegates actual transformation to `ClassInfo` implementations
63+
64+
### ClassInfo Hierarchy
65+
66+
The `ClassInfo` interface provides a unified abstraction for both bytecode and source code representations of Java classes.
67+
68+
#### ByteCodeInfo
69+
70+
`ByteCodeInfo` represents classes loaded from bytecode (.class files).
71+
72+
Implementation details:
73+
- Uses ASM's `ClassNode` as the underlying representation (see [ASM ClassNode documentation](https://asm.ow2.io/javadoc/org/objectweb/asm/tree/ClassNode.html))
74+
- Lazily parses bytecode using [`AsmUtil.getClassNode()`](src/main/java/dev/minco/javatransformer/internal/asm/AsmUtil.java)
75+
- 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)
76+
77+
#### SourceInfo
78+
79+
`SourceInfo` represents classes loaded from source code (.java files) using [JavaParser](https://javaparser.org/).
80+
81+
Implementation details:
82+
- 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
83+
- Parses source code using JavaParser's [`StaticJavaParser`](https://www.javadoc.io/doc/com.github.javaparser/javaparser-core/latest/com/github/javaparser/StaticJavaParser.html)
84+
- 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)
85+
86+
### Transformation Process
87+
88+
1. **Loading**:
89+
- JAR files are processed using `ZipInputStream`
90+
- Folders are traversed using `Files.walkFileTree()`
91+
- Files are categorized as bytecode, source code, or other based on file extension
92+
93+
2. **Parsing**:
94+
- Bytecode: ASM's `ClassReader` is used to create a `ClassNode`
95+
- Source code: JavaParser is used to create a `CompilationUnit` and extract `TypeDeclaration`s
96+
97+
3. **Abstraction**:
98+
- `ByteCodeInfo` or `SourceInfo` objects are created, wrapping the parsed data
99+
- These objects implement the `ClassInfo` interface, providing a unified API
100+
101+
4. **Transformation**:
102+
- General transformers are applied to all `ClassInfo` objects
103+
- Targeted transformers are applied to specific classes based on name matching
104+
- Transformers modify the `ClassInfo`, `MethodInfo`, and `FieldInfo` objects
105+
106+
5. **Code Generation**:
107+
- Bytecode: Modified `ClassNode` objects are written using ASM's `ClassWriter`
108+
- Source code: Modified AST nodes are converted back to source code using JavaParser's pretty-printing capabilities
109+
110+
6. **Saving**:
111+
- Transformed classes are written back to JAR files or folders
112+
- The original file structure is preserved
113+
114+
## CodeFragment System
115+
116+
The `CodeFragment` interface represents a piece of code that can be inserted into a method, supporting both bytecode and source code formats.
117+
118+
### ByteCodeFragment
119+
120+
Represents bytecode instructions.
121+
122+
Implementation details:
123+
- Stores a list of ASM `AbstractInsnNode` objects
124+
- Can be created from raw bytecode instructions or higher-level representations
125+
126+
### SourceCodeFragment
127+
128+
Represents source code snippets.
129+
130+
Implementation details:
131+
- Stores JavaParser `Statement` or `Expression` objects
132+
- Can be created from string literals or pre-parsed AST nodes
133+
134+
### CodeFragmentGenerator
135+
136+
The `CodeFragmentGenerator` interface provides methods to generate `CodeFragment` objects from various input formats.
137+
138+
#### AsmCodeFragmentGenerator
139+
140+
Generates `ByteCodeFragment` objects.
141+
142+
Implementation details:
143+
- Uses ASM to parse and generate bytecode instructions
144+
- Handles conversion between high-level code representations and low-level bytecode
145+
146+
#### SourceCodeFragmentGenerator
147+
148+
Generates `SourceCodeFragment` objects.
149+
150+
Implementation details:
151+
- Uses JavaParser to parse source code snippets into AST nodes
152+
- Handles conversion between string literals and structured AST representations
153+
154+
## Type Resolution and Context
155+
156+
### ResolutionContext
157+
158+
The `ResolutionContext` class provides context for resolving types and members within a class or method.
159+
160+
Implementation details:
161+
- Manages imports, type parameters, and scoping information
162+
- Uses the `ClassPath` to resolve external types
163+
- Implements separate resolution logic for bytecode and source code contexts
164+
165+
### ClassPath
166+
167+
The `ClassPath` class represents the classpath used for resolving types during transformation.
168+
169+
Implementation details:
170+
- Supports both file system and in-memory class loading
171+
- Caches resolved classes for performance
172+
- Handles resolution of array types and primitives
173+
174+
## Utility Classes
175+
176+
### AsmUtil
177+
178+
Provides utility methods for working with ASM.
179+
180+
Key functionalities:
181+
- Reading and writing class files
182+
- Converting between ASM and JavaTransformer type representations
183+
- Generating bytecode for common operations (e.g., method calls, field access)
184+
185+
### JavaParserUtil
186+
187+
Provides utility methods for working with JavaParser.
188+
189+
Key functionalities:
190+
- Parsing and manipulating Java source code
191+
- Converting between JavaParser and JavaTransformer type representations
192+
- Generating AST nodes for common operations
193+
194+
### JVMUtil
195+
196+
Provides utility methods for working with JVM-related concepts.
197+
198+
Key functionalities:
199+
- Converting between class names and file names
200+
- Handling JVM type descriptors and signatures
201+
202+
## Class Loading and Resolution
203+
204+
JavaTransformer employs a sophisticated class loading and resolution system to support its transformation capabilities:
205+
206+
1. **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.
207+
208+
2. **Lazy Initialization**: The `FileClassPath` uses lazy initialization to load classes only when needed, improving performance for large classpaths.
209+
210+
3. **Multiple Formats**: JavaTransformer can load and process both `.class` (bytecode) and `.java` (source code) files, providing a unified `ClassInfo` representation for both.
211+
212+
4. **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.
213+
214+
5. **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.
215+
216+
These class loading and resolution capabilities enable JavaTransformer to perform accurate and context-aware transformations across a wide range of Java code structures and formats.
217+
218+
## Forward Compatibility and JDK Version Support
219+
220+
JavaTransformer aims to maintain compatibility with future JDK versions through several mechanisms:
221+
222+
1. **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:
223+
224+
```java
225+
// TODO: self-test, if we can't load JDK classes with current asm version fall back to reflection
226+
```
227+
228+
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.
229+
230+
2. **Modular JDK Support**: The `SystemClassPath` implementation already includes support for the modular JDK structure introduced in Java 9:
231+
232+
```java
233+
val fs = FileSystems.getFileSystem(URI.create("jrt:/"));
234+
return new FileClassPath(null, Collections.singletonList(fs.getPath("modules/java.base/")));
235+
```
236+
237+
This allows JavaTransformer to work with both traditional and modular JDK structures.
238+
239+
3. **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.
240+
241+
While 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.
242+
243+
## Extension Points for Contributors
244+
245+
To extend or customize JavaTransformer, consider the following areas:
246+
247+
1. **Custom Transformers**: Implement the `Transformer` interface to create new transformation logic.
248+
249+
2. **New CodeFragment Types**: Extend `CodeFragment` to support new ways of representing and inserting code.
250+
251+
3. **Additional File Formats**: Extend the loading and saving logic in `JavaTransformer` to support new file formats beyond JAR and folders.
252+
253+
4. **Enhanced Type Resolution**: Extend `ResolutionContext` or `ClassPath` to improve type resolution capabilities, especially for complex scenarios involving generics or lambda expressions.
254+
255+
5. **Optimization Passes**: Implement transformers that perform bytecode or source code optimizations.
256+
257+
6. **Integration with Other Tools**: Create adapters or wrappers to integrate JavaTransformer with other bytecode or source code manipulation tools.

0 commit comments

Comments
 (0)