easy-agent

Easy proxy bytecode injector at the bytecode level.

Лицензия

Лицензия

Группа

Группа

software.fitz
Идентификатор

Идентификатор

easy-agent
Последняя версия

Последняя версия

0.4.0-RELEASE
Дата

Дата

Тип

Тип

pom
Описание

Описание

easy-agent
Easy proxy bytecode injector at the bytecode level.
Ссылка на сайт

Ссылка на сайт

https://github.com/joongsoo/easy-agent
Система контроля версий

Система контроля версий

https://github.com/joongsoo/easy-agent

Скачать easy-agent

Имя Файла Размер
easy-agent-0.4.0-RELEASE.pom 2 KB
Обзор

Как подключить последнюю версию

<!-- https://jarcasting.com/artifacts/software.fitz/easy-agent/ -->
<dependency>
    <groupId>software.fitz</groupId>
    <artifactId>easy-agent</artifactId>
    <version>0.4.0-RELEASE</version>
    <type>pom</type>
</dependency>
// https://jarcasting.com/artifacts/software.fitz/easy-agent/
implementation 'software.fitz:easy-agent:0.4.0-RELEASE'
// https://jarcasting.com/artifacts/software.fitz/easy-agent/
implementation ("software.fitz:easy-agent:0.4.0-RELEASE")
'software.fitz:easy-agent:pom:0.4.0-RELEASE'
<dependency org="software.fitz" name="easy-agent" rev="0.4.0-RELEASE">
  <artifact name="easy-agent" type="pom" />
</dependency>
@Grapes(
@Grab(group='software.fitz', module='easy-agent', version='0.4.0-RELEASE')
)
libraryDependencies += "software.fitz" % "easy-agent" % "0.4.0-RELEASE"
[software.fitz/easy-agent "0.4.0-RELEASE"]

Зависимости

Библиотека не имеет зависимостей. Это самодостаточное приложение, которое не зависит ни от каких других библиотек.

Модули Проекта

  • easy-agent-core
  • easy-agent-api

easy-agent

This library was created to easily develop a Java agent that injects proxy code into the class bytecode.

If you write code in Java without needing to know the bytecode instrumentation, it is injected into bytecode.

If you want see more info about this framework, See Github wiki documentation

Table of content


🚀 Summary

From an architectural point of view, the Java agent is a good way to inject logic from outside your application.

Many applications are increasingly using cloud and virtualized environments. In that case, there are times when you need to write code that is infrastructure dependent.

For example, if you need to implement istio distributed tracing, You will write code to propagate HTTP headers inside your application.

However, if you write like this, your application will depend to istio.

If using java agent, infrastructure dependent logic can be managed at the infrastructure level. And independence and reusability increase, because it is injected at the infrastructure layer.

image

easy-agent helps you develop java agent easily.


🚀 Feature

Fast

easy-agent uses ASM, it is low-level library. ASM provide high performance.

Easy

You don't need to know bytecode transform. You can easily inject a proxy with simple java code.

Productivity

Productivity is improved by placing infrastructure-dependent code at the infrastructure layer.

You don't have to think about infrastructure when developing and deploying applications. Because the infrastructure-dependent logic is injected by the agent.

Extension

easy-agent provides a easy-agent-api that can be easily extended. You can easily develop reusable plugins.

You can see more info in plugin wiki page.

Documentation

We try to give you the most detailed and friendly documentation possible. If there is any room for improvement in the document, please make a suggestion.


🚀 Extend via plugin

You can make reusable easy-agent plugin. it is very simple. See more details


🚀 Quick start

Just follow 6 simple steps.

(1) Add maven dependency to pom.xml

<dependency>
    <groupId>software.fitz</groupId>
    <artifactId>easy-agent-core</artifactId>
    <version>0.4.0-RELEASE</version>
</dependency>

(2) Implements AroundInterceptor

Override only necessary methods.

public class YourInterceptor implements AroundInterceptor {

    @Override
    public Object[] before(Object target, Method targetMethod, Object[] args) {
        // your proxy code
        if (args[0] instanceof String) {
            args[0] = args[0] + " hi"; // possible replace to target method arguments
        }
        return args;
    }

    @Override
    public Object after(Object target, Method targetMethod, Object returnedValue, Object[] args) {
        // your proxy code
        return returnedValue; // possible replace to return value
    }

    @Override
    public void thrown(Object target, Method targetMethod, Throwable t, Object[] args) {
        // your proxy code
    }
}

(3) Define your plugin & Register interceptor to your target class

public class YourPlugin implements Plugin {

    @Override
    public void setup(TransformerRegistry transformerRegistry) {

        transformerRegistry.register(
                TransformDefinition.builder()
                        // "+" means applies to all classes that extend this class
                        .transformStrategy(TransformStrategy.className("package.Class+")) 
                        .matchArgs(MethodDefinition.all("targetMethodName"))
                        .addInterceptor(YourInterceptor.class)
                        .build()
        );
    }
}

(4) Define premain class & Register your plugin

public class PremainClass {

    public static void premain(String agentArgs, Instrumentation instrumentation) {

        EasyAgentBootstrap.initialize(agentArgs, instrumentation)
                .addPlugin(new YourPlugin())
                .start();
    }
}

(5) Add maven plugin to your pom.xml

  1. Replace {your-jar-name} with the name of the jar you want.
  2. Replace {package.to.premain-class} with a class that implements the premain method.
<plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    <version>2.2</version>
    <executions>
        <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
                <goal>single</goal>
            </goals>
            <configuration>
                <finalName>{your-jar-name}</finalName>
                <appendAssemblyId>false</appendAssemblyId>
                <archive>
                    <manifest>
                        <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
                        <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
                    </manifest>
                    <manifestEntries>
                        <Premain-Class>{package.to.premain-class}</Premain-Class>
                        <Can-Retransform-Classes>true</Can-Retransform-Classes>
                        <Can-Redefine-Classes>true</Can-Redefine-Classes>
                        <Boot-Class-Path>{your-jar-name}.jar</Boot-Class-Path>
                    </manifestEntries>
                </archive>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
        </execution>
    </executions>
</plugin>

(6) Run with your application

Specify your agent jar in the -javaagent argument.

java -javaagent:/path/{your-agent}.jar -jar target-application.jar

🚀 Example

Example of replacing method arguments.

You can see more examples in wiki page.

AroundInterceptor

public class YourInterceptor implements AroundInterceptor {

    @Override
    public Object[] before(Object target, Method targetMethod, Object[] args) {
        if (args[0] != null && args[0] instanceof String) {
            args[0] = args[0] + " Hi!";
        }
        return args;
    }
}

Plugin

The process of registering the module was omitted.

public class YourPlugin implements Plugin {

    @Override
    public void setup(TransformerRegistry transformerRegistry) {

        transformerRegistry.register(
                TransformDefinition.builder()
                        .transformStrategy(TransformStrategy.className("package.TargetClass")) 
                        .addTargetMethod(matchArgs("printName", String.class))
                        .addInterceptor(YourInterceptor.class)
                        .build()
        );
    }
}

Target class & Main class

public class TargetClass {
    
    public void printName(String name) {
        System.out.println(name); 
    }

    public static void main(String[] args) {
        new TargetClass().printName("joongsoo");
    }
}

Execute result

joongsoo Hi!

Версии библиотеки

Версия
0.4.0-RELEASE
0.3.0-RELEASE
0.1.0-RELEASE