Javaagent使用

 

Javaagent使用_第1张图片

 

 

javaagent 简介

Javaagent 只要作用在class被加载之前对其加载,插入我们需要添加的字节码。

javaagent主要作用

 

  • 可以在加载java文件之前做拦截把字节码做修改
  • 可以在运行期将已经加载的类的字节码做变更,但是这种情况下会有很多的限制,后面会详细说
  • 还有其他的一些小众的功能
    • 获取所有已经被加载过的类
    • 获取所有已经被初始化过了的类(执行过了clinit方法,是上面的一个子集)
    • 获取某个对象的大小
    • 将某个jar加入到bootstrapclasspath里作为高优先级被bootstrapClassloader加载
    • 将某个jar加入到classpath里供AppClassload去加载
    • 设置某些native方法的前缀,主要在查找native方法的时候做规则匹配

javaagent的使用

1.通过 -javaagent:xxx.jar=name=ty&age=30

我们通过-javaagent来指定我们编写的agent的jar路径及要传给agent的参数(name=ty&age=30),这样在启动的时候这个agent就可以做一些我们想要它做的事了。

eclipse 中的配置方法:

Javaagent使用_第2张图片

Javaagent使用_第3张图片

javaagent 的简单实例

1. 首先编写java agent类,只需要实现premain这个方法

public class HelloAgent {

	public static void premain(String arg, Instrumentation instrumentation) {
		System.err.println("装载成功 方法 premain 参数:" + arg);
	}
}

2. Agent 类必须打成jar包,然后里面的META-INF/MAINIFEST.MF 必须包含Premain-Class这个属性。

下面是一个MANIFEST.MF的例子:

Manifest-Version: 1.0
Premain-Class:HelloAgent
Created-By:1.6.0_06
然后把MANIFEST.MF 加入到你的jar包中。

maven 使用pom 自动打包,配置如下:

 
           
           
                org.apache.maven.plugins
                maven-jar-plugin
                2.2
                
                    
                        
                            ${project.name}
                            ${project.version}
                            com.ty.javaagent.HelloAgent
                        
                    
                    true
                
            
              
                org.apache.maven.plugins
                maven-compiler-plugin
                2.3.1
                
                    1.7
                    1.7
                    utf8 
                
            
        
    

3.编写测试类

public class TestHelloAgent {
	public static void main(String[] args) {
		System.err.println("TestHelloAgent main 方法");
	}
}

测试结果:

装载成功 方法 premain 参数:name=ty&age=20
TestHelloAgent main 方法

javaagent.jar 和 普通jar区别:

 

  运行时JAR包 javaagent JAR包
入口方法名称 Main premain
Maninfe.MF 主要参数 Main-class Premain-class
启动参数 java -jar xxx.jar -javaagent:xxx.jar
执行顺序  
是否独立启动

javaagent 装载时序如:

Javaagent使用_第4张图片

 

javaagent 修改字节码

public static void premain(String arg, Instrumentation instrumentation) {
		System.err.println("装载成功 方法 premain 参数:" + arg);
		instrumentation.addTransformer(new ClassFileTransformer() {
			public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined,
					ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
				String cname = "com.ty.javaagent.HelloService";
				ClassPool classPool = new ClassPool();
				classPool.insertClassPath(new LoaderClassPath(loader));
				if (className.replaceAll("/", ".").equals(cname)) {
					try {
						CtClass ctClass = classPool.get(cname);
						CtMethod ctMethod = ctClass.getDeclaredMethod("getName");
						ctMethod.insertBefore("System.err.println(System.currentTimeMillis());");

						return ctClass.toBytecode();
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
				return new byte[0];
			}
		});
	}

javasissit的使用参考:https://blog.csdn.net/fd2025/article/details/80279878

Class  装载时序图:

Javaagent使用_第5张图片

javaagent jar 包 MANIFEST.MF 配置参数

#动态agent 类
Agent-Class: com.ty.javaagent.MyAgent
#agent 依懒包逗号分割
Boot-Class-Path: javassist-3.18.1-GA.jar
#是否允许重复装载
Can-Redefine-Classes: true
#静agent 类
Premain-Class: com.ty.javaagent.MyAgent

你可能感兴趣的:(java)