java agent的使用【通俗易懂版】

一、静态代理Agent
1.生成Agent的jar包
(1)创建Agent项目,引入javassist.jar包
(2)编写premain方法

import java.lang.instrument.Instrumentation;

public class Agent1 {

		 
    public static void premain(String agentArgs, Instrumentation inst) {
        System.out.println("agentArgs : " + agentArgs);
        MyAgentTransfer trans = new MyAgentTransfer();
        MyAgentTransferboot trans_boot = new MyAgentTransferboot();
        inst.addTransformer(trans, true);
        inst.addTransformer(trans_boot, true);
    }
	
}

(3)创建MyAgentTransferboot类,实现ClassFileTransformer接口,重写transform方法

import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CodeConverter;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.NotFoundException;
import javassist.expr.ExprEditor;
import javassist.expr.MethodCall;

public class MyAgentTransferboot implements ClassFileTransformer{
	
	/** ClassLoader loader: 类加载器,用于加载当前类的类。 String className: 正在加载的类的名称(用斜杠分隔的形式,例如 java/lang/String)。
		Class<?> classBeingRedefined: 如果这个类正在被重新定义,则为其对应的 Class 对象;否则为 null。 ProtectionDomain protectionDomain: 类的保护域,提供关于类的安全权限的信息。
		byte[] classfileBuffer: 原始的字节码数组。 */
		@Override
		public byte[] transform(ClassLoader loader, String className,
            Class<?> classBeingRedefined, ProtectionDomain protectionDomain,
            byte[] classfileBuffer) throws IllegalClassFormatException {
        byte[] transformed = null;  
//        System.out.println("Transforming className::" + className);  
		if(!className.contains("TaxController") || !className.contains("")) {
        	return classfileBuffer;
        }
        ClassPool pool = null;  
        CtClass cl = null;  
        try {  
            pool = ClassPool.getDefault();
            cl = pool.makeClass(new java.io.ByteArrayInputStream(classfileBuffer));  
//            CtMethod aop_method = pool.get("com.jdktest.instrument.AopMethods").
//                    getDeclaredMethod("aopMethod");
//            System.out.println(aop_method.getLongName());
            CodeConverter convert = new CodeConverter();
             if (cl.isInterface() == false) {  
                CtMethod[] methods = cl.getDeclaredMethods();  
                for (int i = 0; i < methods.length; i++) {  
                    if (methods[i].isEmpty() == false) {  
                       // AOPInsertMethod(methods[i]);  
                        if(methods[i].getName().contains("getUrl") ) {
                                                	System.out.println("methods[i].getName::" + methods[i].getName());  
                        	String name =  methods[i].getName();
                        	methods[i].insertAt(92, "System.out.println(\"---------------Url:\" + Url);");
//                        	methods[i].insertBefore(" System.out.println(\"TTTTTTTTTTTTTTTTTT**********************************************" +name + "\");");
//                        	methods[i].insertBefore(" return \"100\";");
                        }
                    }  
                }  
                transformed = cl.toBytecode();  
            }  
        } catch (Exception e) {  
            System.err.println("Could not instrument  " + className  
                    + ",  exception : " + e.getMessage());  
        } finally {  
            if (cl != null) {  
                cl.detach();  
            }  
        }  
        return transformed;  
    }
    private void AOPInsertMethod(CtMethod method) throws NotFoundException,CannotCompileException {
        method.instrument(new ExprEditor() {  
            @Override
			public void edit(MethodCall m) throws CannotCompileException {  
                m.replace("{ long stime = System.currentTimeMillis(); $_ = $proceed($$);System.out.println(\""
                        + m.getClassName() + "." + m.getMethodName()
                        + " cost:\" + (System.currentTimeMillis() - stime) + \" ms\");}");
            }
        }); 
//      method.insertBefore("System.out.println(\"enter method\");");
//      method.insertAfter("System.out.println(\"leave method\");");
    }

(4)将Agent项目进行打包

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

(5)用压缩包方式打开生成的jar包,打开\META-INF\MANIFEST.MF文件,添加如下代码:

Can-Redefine-Classes: true
Can-Retransform-Classes: true
Premain-Class: com.javaAgent.Agent1

2.在项目中使用agent
在这里插入图片描述
在这里插入图片描述

命令:-javaagent:jar包地址=参数
如:-javaagent:D:\Work_Code\javaAgent\StringLenAgent.jar=‘1’
-javaagent:D:\Work_Code\javaAgent\StringLenAgent.jar

二、动态代理Attach
1.生成Attach的jar包
(1)创建Attach项目,引入javassist.jar包、com.sun.tools.attach-1.8.0_jdk8u172-b11.jar包
(2)编写agentmain方法

import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;

public class Attach1 {
	public static void agentmain(String attachArgs, Instrumentation instrumentation) {
		System.out.println("attach agentmain启动");
		System.out.println("attachArgs : " + attachArgs);
        Class<?>[] classes = instrumentation.getAllLoadedClasses();
        for (Class<?> cls : classes) {
            String className = cls.getName();
            if(className.contains("TaxController")) {
                CtClass ctClass;
                try {
                    ClassPool classPool = ClassPool.getDefault();
                    ctClass = classPool.get(className);
                    CtMethod[] methods = ctClass.getDeclaredMethods();  
                    for (int i = 0; i < methods.length; i++) {  
                        if (methods[i].isEmpty() == false) {  
                           // AOPInsertMethod(methods[i]);  
                            if(methods[i].getName().contains("getUrl") ) {
                            	System.out.println("methods[i].getName::" + methods[i].getName());  
                            	String name =  methods[i].getName();
                            	methods[i].insertAt(92, "System.out.println(\"---------------Url:\" + Url);");
//                            	methods[i].insertBefore(" System.out.println(\"TTTTTTTTTTTTTTTTTT**********************************************" +name + "\");");
//                            	methods[i].insertBefore(" return \"100\";");
                            }
                        }  
                    }  
                    ClassDefinition classDefinition = new ClassDefinition(cls, ctClass.toBytecode());
                    instrumentation.redefineClasses(classDefinition);
                } catch (Throwable e) {
                    System.out.println(e.getMessage());
                    e.printStackTrace();
                }
            }
          

(3)将Attach项目进行打包
(4)用压缩包方式打开生成的jar包,打开\META-INF\MANIFEST.MF文件,添加如下代码:
Agent-Class: com.javaAttach.Attach1
Can-Redefine-Classes: true
Can-Retransform-Classes: true
(5)启动需被代理的应用程序
编写main方法,给需被代理的应用程序添加代理

import java.util.concurrent.TimeUnit;
import com.sun.tools.attach.*;

public class AttachUseMain {
	public static void main(String[] args) throws Exception{
        System.out.println("AttachUseMain启动");
        long start = System.currentTimeMillis();
		System.out.println(start);
        for (VirtualMachineDescriptor vmd : VirtualMachine.list()) {
            String name = vmd.displayName();
            System.out.println(name + ":" + vmd.id());
            if (name.contains("Application")) {
                VirtualMachine vm = VirtualMachine.attach(vmd.id());
//                vm.loadAgent("D:\\Work_Code\\javaAgent\\StringLenAttach.jar=hello,ok,aa,bb,cc=3");
                vm.loadAgent("D:\\Work_Code\\javaAgent_1\\javaAttach\\StringLenAttach004.jar=22");
                TimeUnit.MINUTES.sleep(1);
                vm.detach();
                System.out.println("Agent 已成功附加到目标 JVM");
            }
        }
        
        long end = System.currentTimeMillis();
		System.out.println(end - start);
//        String targetPid = "25304"; //jps -l
//        // 指定要附加的 Agent JAR 路径
//        String agentPath = "D:\\Work_Code\\javaAgent\\StringLenAttach.jar";
//
//        // 附加到目标 JVM
//        VirtualMachine vm = VirtualMachine.attach(targetPid);
//        // 加载 Agent
//        vm.loadAgent(agentPath);
//        // 断开连接
//        vm.detach();
        System.out.println("over");
    }
}
<think>好的,我现在需要帮助用户解决Git推送时出现的“Permission denied (publickey)”问题。首先,我应该回顾用户提供的引用内容,看看里面有没有有用的信息。 引用[1]提到,这个问题是因为当前电脑中没有公钥导致的。解决步骤包括生成公钥并添加到GitHub账户。用户还遇到了查看公钥时提示文件不存在的情况,这说明用户可能还没有生成过SSH密钥。所以第一步应该是检查是否存在公钥,如果不存在,就需要生成新的。 引用[2]指出即使已经生成了.ssh目录并上传了公钥,仍然可能遇到问题。这时候可能需要检查权限设置是否正确,或者是否配置了正确的SSH代理。比如,文件权限太开放可能会导致SSH拒绝使用密钥。 引用[3]中的用户尝试克隆仓库时,系统提示无法验证主机,但在确认后仍然出现权限被拒绝。这可能意味着SSH密钥没有正确关联到GitHub账户,或者使用的密钥不是默认名称,需要配置config文件。 接下来,我需要将这些信息整理成步骤。首先,确认是否存在公钥,如果没有就生成;然后确保公钥正确添加到GitHub;接着检查SSH代理是否运行;再检查文件权限是否正确;如果使用非默认密钥名称,需要配置SSH的config文件;最后建议测试连接。此外,可能还需要处理首次连接时的known_hosts问题,以及多账户的情况。 用户的问题是关于git push时出现该错误,所以需要特别强调推送相关的配置是否和克隆时一致。例如,远程仓库的URL是否使用SSH格式,而不是HTTPS,因为后者可能需要密码而不是SSH密钥。 另外,可能需要提醒用户,如果在生成密钥时设置了密码,每次使用都需要输入,或者配置ssh-agent来保存密码。还有,GitHub账户中添加的公钥内容是否正确,有没有多余的换行或缺失。 最后,应该验证步骤是否全面,是否覆盖了常见的解决方法,比如权限问题、代理问题、多密钥配置等。同时要确保语言通俗易懂,步骤清晰,用户能够一步步跟随操作。</think>### Git推送出现"Permission denied (publickey)"的解决方案 当遇到`git push`操作时提示`Permission denied (publickey)`,说明本地SSH密钥配置与GitHub账户认证失败。以下是详细解决步骤: #### 第一步:验证SSH密钥存在性 1. 打开Git Bash终端 2. 执行命令检查密钥文件: ```bash ls -al ~/.ssh ``` 若未显示`id_rsa`和`id_rsa.pub`文件(或`id_ed25519`等新密钥),说明需要生成新密钥[^1]。 #### 第二步:生成新SSH密钥 ```bash ssh-keygen -t rsa -b 4096 -C "your_email@example.com" ``` 生成过程中按3次回车: - 保持默认保存路径`(/c/Users/you/.ssh/id_rsa)` - 空密码(若需安全可设置密码) - 确认密码(若前步设置) #### 第三步:添加密钥到SSH代理 ```bash eval "$(ssh-agent -s)" ssh-add ~/.ssh/id_rsa ``` #### 第四步:绑定密钥到GitHub账户 1. 复制公钥内容: ```bash cat ~/.ssh/id_rsa.pub ``` 2. 登录GitHub → Settings → SSH and GPG keys → New SSH key 3. 粘贴公钥(完整内容包含`ssh-rsa`前缀和邮箱后缀) #### 第五步:验证连接状态 ```bash ssh -T git@github.com ``` 成功时会显示: ```bash Hi username! You've successfully authenticated... ``` #### 第六步:检查仓库远程地址 确保仓库使用SSH协议地址: ```bash git remote set-url origin git@github.com:username/repo.git ``` #### 第七步:文件权限修复 ```bash chmod 700 ~/.ssh chmod 600 ~/.ssh/* ``` #### 特殊场景处理 1. **多密钥共存**:创建`~/.ssh/config`文件配置不同仓库 ```bash Host github.com HostName github.com User git IdentityFile ~/.ssh/id_rsa_work ``` 2. **Windows凭证冲突**:在控制面板→凭据管理器删除Git相关凭据
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值