Table of Contents
Introduction to Java Agent technology
Java Agent function introduction
Mainly intercepts and modifies the bytecode before class loading
Maven
Home Java javaTutorial How to use Java Agent

How to use Java Agent

May 22, 2023 pm 08:52 PM
java agent

Introduction to Java Agent technology

Java Agent is literally translated as Java agent, and is also often called Java probe technology.

Java Agent This technology was introduced in JDK1.5 and can dynamically modify Java bytecode at runtime. Classes in Java are compiled to form bytecodes that are executed by the JVM. The JVM obtains the information of these bytecodes before executing these bytecodes, and modifies these bytecodes through a bytecode converter to complete the process. Some extra features.

Java Agent is a jar package that cannot run independently. It works through the JVM process attached to the target program. When starting, you only need to add the -javaagent parameter to the startup parameters of the target program to add ClassFileTransformer bytecode converter, which is equivalent to adding an interceptor before the main method.

Java Agent function introduction

Java Agent mainly has the following functions:

  • Java Agent can Intercept and modify the Java bytecode before loading;

  • Java Agent can modify the loaded bytecode while the Jvm is running;

Application scenarios of Java Agent:

  • Debugging function of IDE, such as Eclipse, IntelliJ IDEA;

  • Hot deployment functions, such as JRebel,

  • # Various performance analysis tools, such as Visual VM, JConsole, etc.;
  • Full-link performance detection tools, such as Skywalking, Pinpoint, etc.;
  • Java Agent implementation principle
  • Before understanding the implementation principle of

    Java Agent
  • , you need to have a clear understanding of the Java class loading mechanism. One is to execute through premain before the man method is executed, and the other is to modify the program while it is running, which needs to be implemented through Attach in the JVM. The implementation principle of Attach is based on JVMTI.

Mainly intercepts and modifies the bytecode before class loading

Let’s introduce these key terms respectively:

JVMTI is

JVM Tool Interface
    , which is a collection of interfaces exposed by the JVM for user extensions. JVMTI is event-driven and will be triggered every time the JVM executes certain logic. Callback interfaces for some events. Through these callback interfaces, users can extend themselves
  • JVMTI is the unified basis for implementing tools such as Debugger, Profiler, Monitor, Thread Analyser, etc., in mainstream Java virtual machines All are implemented

JVMTIAgent

is a dynamic library that uses some interfaces exposed by JVMTI to do things we want to do but cannot do under normal circumstances. thing, but in order to distinguish it from ordinary dynamic libraries,

it generally implements one or more functions as follows:
  • ##Agent_OnLoad Function, if the agent is loaded at startup, set it through JVM parameters

    • Agent_OnAttach Function, if the agent is not loaded at startup, but us First attach to the target process, and then send the load command to the corresponding target process to load. The Agent_OnAttach function

    • Agent_OnUnload function will be called during the loading process. When the agent is uninstalled, it is called

    • javaagent which depends on the instrument's JVMTIAgent (the corresponding dynamic library under Linux is libinstrument.so), and there are also individuals named

      JPLISAgent
    • (Java Programming Language Instrumentation Services Agent), which specifically provides support for instrumentation services written in Java language
  • instrument implements Agent_OnLoad and Agent_OnAttach has two methods, which means that when used, the agent can be loaded at startup or dynamically loaded at runtime. Loading at startup can also indirectly load instrument agent

    through a method similar to -javaagent:jar package path. Dynamic loading at runtime relies on the JVM's attach mechanism, and the agent
  • is loaded by sending the load command.
  • JVM Attach refers to an inter-process communication function provided by JVM, which allows one process to pass commands to another process and perform some internal operations, such as Thread dump, then you need to execute jstack, and then pass the pid and other parameters to the thread that needs to dump to execute

  • Java Agent case

    We will use the print method Taking the execution time as an example, it is achieved through Java Agent

    .
First we need to build a streamlined

Maven

project, in which we build two Maven sub-projects, one for implementing the plug-in Agent, and one for implementing the test target program.

We import the packages that the two projects have common dependencies on in the parent application

    <dependencies>
        <dependency>
            <groupId>org.javassist</groupId>
            <artifactId>javassist</artifactId>
            <version>3.28.0-GA</version>
        </dependency>
    </dependencies>
Copy after login

How to use Java AgentFirst we build the test Target program

// 启动类
public class APPMain {
    public static void main(String[] args) {
        System.out.println("APP 启动!!!");
        AppInit.init();
    }
}
// 模拟的应用初始化的类
public class AppInit {
    public static void init() {
        try {
            System.out.println("APP初始化中...");
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
Copy after login

然后我们启动程序,测试是否能正常执行,程序正常执行之后,我们开始构建探针程序

探针程序中我们需要编写,改变原有class的Transformer,通过自定义的Transformer类完成输出方法执行时间的功能,

How to use Java Agent

首先构检Agent程序的入口

public class RunTimeAgent {
    public static void premain(String arg, Instrumentation instrumentation) {
        System.out.println("探针启动!!!");
        System.out.println("探针传入参数:" + arg);
        instrumentation.addTransformer(new RunTimeTransformer());
    }
}
Copy after login

这里每个类加载的时候都会走这个方法,我们可以通过className进行指定类的拦截,然后借助javassist这个工具,进行对Class的处理,这里的思想和反射类似,但是要比反射功能更加强大,可以动态修改字节码。

javassist是一个开源的分析、编辑和创建Java字节码的类库。

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
public class RunTimeTransformer implements ClassFileTransformer {
    private static final String INJECTED_CLASS = "com.zhj.test.init.AppInit";
    @Override
    public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
        String realClassName = className.replace("/", ".");
        if (realClassName.equals(INJECTED_CLASS)) {
            System.out.println("拦截到的类名:" + realClassName);
            CtClass ctClass;
            try {
                // 使用javassist,获取字节码类
                ClassPool classPool = ClassPool.getDefault();
                ctClass = classPool.get(realClassName);
                // 得到该类所有的方法实例,也可选择方法,进行增强
                CtMethod[] declaredMethods = ctClass.getDeclaredMethods();
                for (CtMethod method : declaredMethods) {
                    System.out.println(method.getName() + "方法被拦截");
                    method.addLocalVariable("time", CtClass.longType);
                    method.insertBefore("System.out.println(\"---开始执行---\");");
                    method.insertBefore("time = System.currentTimeMillis();");
                    method.insertAfter("System.out.println(\"---结束执行---\");");
                    method.insertAfter("System.out.println(\"运行耗时: \" + (System.currentTimeMillis() - time));");
                }
                return ctClass.toBytecode();
            } catch (Throwable e) { //这里要用Throwable,不要用Exception
                System.out.println(e.getMessage());
                e.printStackTrace();
            }
        }
        return classfileBuffer;
    }
}
Copy after login

我们需要在Maven中配置,编译打包的插件,这样我们就可以很轻松的借助Maven生成Agent的jar包

<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version>
                <!-- 指定maven编译的jdk版本。若不指定,maven3默认用jdk 1.5 maven2默认用jdk1.3 -->
                <configuration>
                    <source>8</source>
                    <target>8</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.2.0</version>
                <configuration>
                    <archive>
                        <!--自动添加META-INF/MANIFEST.MF -->
                        <manifest>
                            <addClasspath>true</addClasspath>
                        </manifest>
                        <manifestEntries>
                            <Menifest-Version>1.0</Menifest-Version>
                            <Premain-Class>com.zhj.agent.RunTimeAgent</Premain-Class>
                            <Can-Redefine-Classes>true</Can-Redefine-Classes>
                            <Can-Retransform-Classes>true</Can-Retransform-Classes>
                        </manifestEntries>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>
Copy after login

否则我们需要在resources下创建META-INF/MANIFEST.MF文件,文件内容如下,我们可以看出这个与Maven中的配置是一致的,然后通过配置编译器,借助编译器打包成jar包,需指定该文件

Manifest-Version: 1.0
Premain-Class: com.zhj.agent.RunTimeAgent
Can-Redefine-Classes: true
Can-Retransform-Classes: true
Copy after login

告示文件MANIFEST.MF参数说明:

Manifest-Version

文件版本

Premain-Class

包含 premain 方法的类(类的全路径名)main方法运行前代理

Agent-Class

包含 agentmain 方法的类(类的全路径名)main开始后可以修改类结构

Boot-Class-Path

设置引导类加载器搜索的路径列表。查找类的特定于平台的机制失败后,引导类加载器会搜索这些路径。按列出的顺序搜索路径。列表中的路径由一个或多个空格分开。(可选)

Can-Redefine-Classes true

表示能重定义此代理所需的类,默认值为 false(可选)

Can-Retransform-Classes true

表示能重转换此代理所需的类,默认值为 false (可选)

Can-Set-Native-Method-Prefix true

表示能设置此代理所需的本机方法前缀,默认值为 false(可选)

最后通过Maven生成Agent的jar包,然后修改测试目标程序的启动器,添加JVM参数即可

参数示例:-javaagent:F:\code\myCode\agent-test\runtime-agent\target\runtime-agent-1.0-SNAPSHOT.jar=hello

How to use Java Agent

最终效果:

How to use Java Agent

The above is the detailed content of How to use Java Agent. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
2 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
Repo: How To Revive Teammates
4 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: How To Get Giant Seeds
4 weeks ago By 尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Square Root in Java Square Root in Java Aug 30, 2024 pm 04:26 PM

Guide to Square Root in Java. Here we discuss how Square Root works in Java with example and its code implementation respectively.

Perfect Number in Java Perfect Number in Java Aug 30, 2024 pm 04:28 PM

Guide to Perfect Number in Java. Here we discuss the Definition, How to check Perfect number in Java?, examples with code implementation.

Random Number Generator in Java Random Number Generator in Java Aug 30, 2024 pm 04:27 PM

Guide to Random Number Generator in Java. Here we discuss Functions in Java with examples and two different Generators with ther examples.

Weka in Java Weka in Java Aug 30, 2024 pm 04:28 PM

Guide to Weka in Java. Here we discuss the Introduction, how to use weka java, the type of platform, and advantages with examples.

Armstrong Number in Java Armstrong Number in Java Aug 30, 2024 pm 04:26 PM

Guide to the Armstrong Number in Java. Here we discuss an introduction to Armstrong's number in java along with some of the code.

Smith Number in Java Smith Number in Java Aug 30, 2024 pm 04:28 PM

Guide to Smith Number in Java. Here we discuss the Definition, How to check smith number in Java? example with code implementation.

Java Spring Interview Questions Java Spring Interview Questions Aug 30, 2024 pm 04:29 PM

In this article, we have kept the most asked Java Spring Interview Questions with their detailed answers. So that you can crack the interview.

Break or return from Java 8 stream forEach? Break or return from Java 8 stream forEach? Feb 07, 2025 pm 12:09 PM

Java 8 introduces the Stream API, providing a powerful and expressive way to process data collections. However, a common question when using Stream is: How to break or return from a forEach operation? Traditional loops allow for early interruption or return, but Stream's forEach method does not directly support this method. This article will explain the reasons and explore alternative methods for implementing premature termination in Stream processing systems. Further reading: Java Stream API improvements Understand Stream forEach The forEach method is a terminal operation that performs one operation on each element in the Stream. Its design intention is

See all articles