一:认识一下 JavaAgent(实操)

本文介绍了JavaAgent的概念及其在进程启动前后的应用,通过一个实际操作的步骤演示了如何创建并使用JavaAgent,包括打包配置、MANIFEST.MF文件的编辑等。此外,还列举了一系列关于字节码修改、类加载等问题,暗示后续将深入探讨这些问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JavaAgent

1.0 先看几个面试题:

  • 怎么获取某个对象的大小?
  • 运行期将已经加载的类的字节码能做变更吗,怎么做?有什么限制?
  • 如何获取所有已经被加载过的类?
  • 怎么在加载java文件之前做拦截把字节码做修改?
  • 如何获取所有已经被初始化过了的类(clinit后的方法)
  • 如何设置某些native方法的前缀?
  • 如何在查找native方法的时候做规则匹配?
  • 如何将某个jar加入到bootstrapclasspath 里作为高优先级被bootstrapClassloader 加载?
  • AppClassloader怎么去加载某个加入到 classpath 里的 jar?

我:…(#$%^&*)

1.1 先从来源说起

JavaAgent 是JDK 1.5 以后引入的,也可以叫做Java代理。

JavaAgent 是运行在 main方法之前的拦截器,它内定的方法名叫 premain ,也就是说先执行 premain 方法然后再执行 main 方法。

主要功能如下:

  • 看问题 1.0

按照加载时机可以分为两种:

  • 进程启动前
  • 进程启动后

1.2 如何实操?

准备工作:

  • 电脑一台、带键盘鼠标显示器,能通电能开机,内存512M,一核CPU,差不多就行
  • 安装 jdk(1.8) ,安装 IDEA(2021.2.4),安装 maven

实施步骤:

  • 首先创建一个 Java Aganet 的 maven 项目,步骤如下:

    打开 IDEA:
    在这里插入图片描述

    新建项目:

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

走到这一步的小伙伴就可以编写具体的 JavaAgent 的代码了。

在这里插入图片描述

在这里插入图片描述

​ 具体代码:

package com.carrot.sec;

import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;

public class MyAgent {

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

        System.err.println("MyAgent 开始执行了! , 参数是 " + arg);

        //注册我们的函数
        instrumentation.addTransformer(new ClassFileTransformer() {

            public byte[] transform(
                    ClassLoader loader,
                    String className,
                    Class<?> classBeingRedefined,
                    ProtectionDomain protectionDomain,
                    byte[] classfileBuffer
            ) throws IllegalClassFormatException {

                System.out.println("加载的类名字是: " + className);

                return classfileBuffer;
            }

        });

    }

}

写好了就打包一个 java 的 jar 包。

pom文件增加以下内容:

<build>
        <plugins>

            <!-- jdk 1.8 编译 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>8</source>
                    <target>8</target>
                </configuration>
            </plugin>

            <!-- java agent -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifestFile>src/main/resources/META-INF/MANIFEST.MF</manifestFile>
                    </archive>
                </configuration>
            </plugin>

        </plugins>
    </build>

执行 maven 打包命令:

在这里插入图片描述

在这里插入图片描述

mvn clean package -U -DMaven.test.skip=true

在这里插入图片描述

出现这个错误,不要慌,去 resources 下手动创建 pom 文件里面指定的目录:src/main/resources/META-INF/MANIFEST.MF

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

META-INF/MANIFEST.MF 的内容:

Manifest-Version: 1.0
Premain-Class: com.carrot.sec.MyAgent
Can-Redefine-Classes: true
Can-Retransform-Classes: true

属性说明是否必填默认值
Premain-Class包含premain方法的类依赖启动方式
Agent-Class包含agentmain方法的类依赖启动方式
Boot-Class-Path启动类加载器搜索路径
Can-Redefine-Classis是否可以重定义代理所需的类false
Can-Retransform-Classis是否能够重新转换此代理所需的类false
Can-Set-Native-Method-Prefix是否能够设置此代理所需的本机方法前缀false

再次打包就可以了。。。

在这里插入图片描述

找到 jar 包,检查里面的内容,如果不对就修改一下。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
没啥问题就过了。。。

  • 再建一个普通的项目,我这边比较懒直接建了个 Spring boot 项目。
  • 步骤如下:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

IDEA中的VM命令

-javaagent:D:\local-project\FirstAgent\target\FirstAgent-1.0-SNAPSHOT.jar
这些工作做完了之后就可以启动我们的 Spring Boot 项目了。

在这里插入图片描述

假如你想用命令来启动,也是可以做到的:

  • 把 Spring Boot 项目打包,和 MyAgent 的打包方式是一样的~~~

  • 找到 Spring Boot 的 jar 包的位置,也找到 MyAgent 的位置。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

  • 执行命令:

    java -javaagent:D:\local-project\FirstAgent\target\FirstAgent-1.0-SNAPSHOT.jar -jar demo-0.0.1-SNAPSHOT.jar
    

更多的用法或者用途,我们一起发现一起创造!
比如:

  • 怎么获取某个对象的大小?
  • 运行期将已经加载的类的字节码能做变更吗,怎么做?有什么限制?
  • 如何获取所有已经被加载过的类?
  • 怎么在加载java文件之前做拦截把字节码做修改?
  • 如何获取所有已经被初始化过了的类(clinit后的方法)
  • 如何设置某些native方法的前缀?
  • 如何在查找native方法的时候做规则匹配?
  • 如何将某个jar加入到bootstrapclasspath 里作为高优先级被bootstrapClassloader 加载?
  • AppClassloader怎么去加载某个加入到 classpath 里的 jar?

这些案例会抽时间逐一做出解答。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值