https://github.com/nazmulidris/java-agent
Example of a JVM instrumentation agent
https://github.com/nazmulidris/java-agent
Last synced: 7 months ago
JSON representation
Example of a JVM instrumentation agent
- Host: GitHub
- URL: https://github.com/nazmulidris/java-agent
- Owner: nazmulidris
- License: apache-2.0
- Created: 2020-05-04T00:04:49.000Z (over 5 years ago)
- Default Branch: main
- Last Pushed: 2024-11-26T18:56:07.000Z (11 months ago)
- Last Synced: 2025-01-23T20:09:27.232Z (9 months ago)
- Language: Java
- Size: 30.3 KB
- Stars: 0
- Watchers: 3
- Forks: 0
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
# java-instrumentation-agent
- [Running this on your machine](#running-this-on-your-machine)
- [Notes on building this project](#notes-on-building-this-project)
- [What goes where](#what-goes-where)
- [Building the agent using Maven](#building-the-agent-using-maven)
- [Resources](#resources)
- [Tutorials on building Java agents](#tutorials-on-building-java-agents)
- [Background on Java bytecode generation](#background-on-java-bytecode-generation)
- [Background information on the instrumentation API](#background-information-on-the-instrumentation-api)
- [Background information on agents](#background-information-on-agents)This project shows how to use the Java instrumentation API to add some runtime monitoring to an already created and
running application using byte code generation.## Running this on your machine
Open the project in IDEA, and then you will see the following run configurations.
1. `Main ` - This simply starts the `application.Main` class and you will see usage instructions printed
to the console.
2. `Main start 10000 10 1000` - This actually starts the main application which does the following:
- Makes an ATM withdrawal for `10` units.
- Sleeps for `10_000` ms (this is your chance to attach the agent to see it instrument the ATM).
- Makes a 2nd ATM withdrawal for `1000` units.
3. `Main loadagent` - This actually starts the main application and tells it to load the agent, which will attach
to an already existing running VM that has executed `start` (above).So, to play with it, make sure that you build the entire project first. There's a maven task that runs everytime
the project is rebuilt called `install`. You can see this in the Maven tool window.1. The first thing you can do is run the `Main ` run configuration just to see the command line usage of the
`application.Main` class.
2. Then you can run the `Main start...` configuration and it will perform one ATM
withdrawal and wait for 10 sec.
3. Then you can run the `Main loadagent` configuration and it will attach to the VM started above, and will instrument
the ATM code by adding some byte code generated using [`javassist`](https://www.javassist.org/). You can see the
output of this byte code injection into your ATM class and it will dump some instrumentation output to the console.## Notes on building this project
### What goes where
This project is really broken out into two main parts.
1. `application` package - this is the code for the application, the ATM, and the agent loader. The instrumentation code and byte code generation does not exist in the `application` package. You can run that
indepedently of the instrumentation code, by simply running `App#main()`.
2. `agent` package - the code here is used to generate bytecode and use the instrumentation API. This code is what is
built by Maven along w/ the `MANIFEST.MF` file into a JAR file (`target/java-instrumentation-agent-0.1.0-SNAPSHOT.jar`).
This JAR file is loaded by the `application.AgentLoader` into the VM that is running the `Main start...` run
configuration (the `application` package).### Building the agent using Maven
There is a `MANIFEST.MF` file that is in the `resources/META-INF` folder which is used by Maven to generate the
agent JAR file. In IDEA, in the Maven tool window, you will find that the `install` task is run after a full rebuild
of the project in IDEA. Here's the code from the `pom.xml` that does this.```xml
org.apache.maven.plugins
maven-jar-plugin
${maven.jar.plugin.version}
src/main/resources/META-INF/MANIFEST.MF
```
Also, it was useful to use the following command to debug the maven `install` task from the command line, which
generates some really helpful debug messages during compilation and packaging the agent JAR file.```shell script
mvn clean install -X
```## Resources
### Tutorials on building Java agents
- [Guide to Java Instrumentation (lacking lots of details)](https://www.baeldung.com/java-instrumentation)
- [Repo of samples "core-java-jvm" on GitHub (lacking lots of details)](https://github.com/eugenp/tutorials/tree/master/core-java-modules/core-java-jvm)
- [Maven clean and install](https://stackoverflow.com/a/20122552/2085356)
- [Example of using maven to package an agent](https://dhruba.wordpress.com/2010/02/07/creation-dynamic-loading-and-instrumentation-with-javaagents/)
- [Example of using IDEA and maven to build an agent](https://stackify.com/what-are-java-agents-and-how-to-profile-with-them/)### Background on Java bytecode generation
- [Tutorial on using bytecode generation via Javassist library](https://www.baeldung.com/javassist)
- [Javaassist library](http://www.javassist.org/)### Background information on the instrumentation API
- [Javadocs: instrumentation API](https://docs.oracle.com/javase/7/docs/api/java/lang/instrument/Instrumentation.html)
Basically, the API allows adding code before or after already existing code (w/out modifying any of the existing code
itself). Or you can simply swap out entire classes. Here's a short list of things you can do with this API:1. `addTransformer` – adds a transformer to the instrumentation engine
2. `getAllLoadedClasses` – returns an array of all classes currently loaded by the JVM
3. `retransformClasses` – facilitates the instrumentation of already loaded classes by adding byte-code
4. `removeTransformer` – unregisters the supplied transformer
5. `redefineClasses` – redefine the supplied set of classes using the supplied class files, meaning that the class will
be fully replaced, not modified as with `retransformClasses`Sample project that shows how to use this (and agents from the section below):
[repo](https://github.com/eugenp/tutorials/tree/master/core-java-modules/core-java-jvm).### Background information on agents
In general, a java agent is just a specially crafted jar file. It utilizes the
[Instrumentation API](https://docs.oracle.com/javase/7/docs/api/java/lang/instrument/Instrumentation.html) that the JVM
provides to alter existing byte-code that is loaded in a JVM.For an agent to work, we need to define two methods:
- `premain` – will **statically** load the agent using `-javaagent` parameter at JVM startup. Static load modifies the
byte-code at startup time before any code is executed.
- `agentmain` – will **dynamically** load the agent into an already running JVM using the
[Java Attach API](https://docs.oracle.com/javase/7/docs/jdk/api/attach/spec/com/sun/tools/attach/package-summary.html)Basics, IDE specific guides, API references:
- [Tutorial: Basic Java Agent in IDEA](https://stackify.com/what-are-java-agents-and-how-to-profile-with-them/)
- [Tutorial: Basic Java Agent](https://www.developer.com/java/data/what-is-java-agent.html)
- [JDK5 instrumentation API](https://docs.oracle.com/javase/7/docs/api/java/lang/instrument/package-summary.html)Good tutorials & slides (these give an idea of what can be done w/ agents):
- [Tutorial: Guide to Java instrumentation](https://www.baeldung.com/java-instrumentation)
- [Slide deck on Java agents](https://speakerdeck.com/shelajev/taming-javaagents-bcn-jug-2015)
- [Tutorial: Quick intro to Java agents](https://www.jrebel.com/blog/how-write-javaagent)
- [Tutorial: Quick intro to Java agents](https://www.javacodegeeks.com/2015/09/java-agents.html)
- [Tutorial: Quick intro to Java agents](https://javapapers.com/core-java/java-instrumentation/)
- [Tutorial: Quick intro to Java agents](https://www.javamex.com/tutorials/memory/instrumentation.shtml)Interesting libraries related to agents (good to look at source):
- [Extensible java agent framework](https://github.com/brutusin/instrumentation)