Java Instrumentation (参考:http://www.ibm.com/developerworks/cn/java/j-lo-jse61/

简介:

使用Instrumentation,开发者可以构建独立于应用程序的代理程序,用来检测和协助运行在JVM上的程序,甚至能够替换和修改某些类的定义

遇到问题:

运行在tomcat容器中的应用程序,由于main方法是在Bootstrap.jar中容器启动时执行的,

Agent-class方式在替换的方法中只获取到tomcat相关jar包中的一些类:

上图中是在transform方法中打印出来的,这个方法会在二中介绍

具体介绍:

下面是两种方式PreMain 和 agentMain,分别为main函数执行之前,和执行之后的操作

一:PreMain

main函数执行之间,扫描判断特定的类,然后以字节数组的方式加载代理类的字节码文件,替换目标类:

示例代码:

public class TransClass {
public int getNumber() {
return 2;
}
}

TransClass

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain; class Transformer implements ClassFileTransformer {
public static final String classNumberReturns2 = "D://AOP//TransClass.class.2";
public static byte[] getBytesFromFile(String fileName) {
try {
// precondition
File file = new File(fileName);
InputStream is = new FileInputStream(file);
long length = file.length();
byte[] bytes = new byte[(int) length]; // Read in the bytes
int offset = 0;
int numRead = 0;
while (offset <bytes.length && (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) {
offset += numRead;
}
if (offset < bytes.length) {
throw new IOException("Could not completely read file "+ file.getName());
}
is.close();
return bytes;
} catch (Exception e) {
System.out.println("error occurs in _ClassTransformer!"+ e.getClass().getName());
return null;
}
} public byte[] transform(ClassLoader l, String className, Class<?> c,
ProtectionDomain pd, byte[] b) throws IllegalClassFormatException {
if (!className.equals("TransClass")) {
return null;
}
return getBytesFromFile(classNumberReturns2);
}
}

Transformer

public class TestMainInJar {
public static void main(String[] args) {
System.out.println(new TransClass().getNumber());
}
}

TestMainInJar

import java.lang.instrument.UnmodifiableClassException;
import java.lang.instrument.Instrumentation;
public class Premain {
public static void premain(String agentArgs, Instrumentation inst)
throws ClassNotFoundException, UnmodifiableClassException {
inst.addTransformer(new Transformer());
}
}

Premain

Manifest-Version: 1.0
Premain-Class: Premain

MANIFEST.MF

步骤:

1. TransClass.java 中 改成 return 2; 之后编译生成的TransClass.class改名为TransClass.class.2 ,以防止跟原TransClass.class重名

2. 打包:jar -cvf0 TestInstrument1.jar TransClass.class Transformer.class TestMainInJar.class Premain.class

打好jar后替换manifest.mf文件,(没找到怎么把这个文件直接打进jar包)

3. 命令行执行

1)java -javaagent:TestInstrument1.jar -cp TestInstrument1.jar TestMainInJar

2)java -cp TestInstrument1.jar TestMainInJar

 (TransClass.class.2 和 TestInstrument1.jar 需要放置到  D:\AOP 目录下)

用第一个命令执行的时候,会把TransClass.class.2的内容加载进来替换jar包中的TransClass.class,而第二个命令是正常执行jar包中的TransClass.class

二: Agent-class

import java.lang.instrument.Instrumentation;

public class LoadedAgent {
@SuppressWarnings("rawtypes")
public static void agentmain(String args, Instrumentation inst){
Class[] classes = inst.getAllLoadedClasses();
//inst.addTransformer(new Transformer());
for(Class cls :classes){
System.out.println(cls.getName());
}
}
}

LoadedAgent

public class TargetVM {
public static void main(String[] args) throws InterruptedException{
while(true){
Thread.sleep(1000);
}
}
}

TargetVM

import java.io.IOException;

import com.sun.tools.attach.AgentInitializationException;
import com.sun.tools.attach.AgentLoadException;
import com.sun.tools.attach.AttachNotSupportedException;
import com.sun.tools.attach.VirtualMachine; public class Test {
public static void main(String[] args) throws AttachNotSupportedException,
IOException, AgentLoadException, AgentInitializationException {
VirtualMachine vm = VirtualMachine.attach("1244");
vm.loadAgent("D:/AOP/agentmain/agentAop.jar"); } }

Test

Manifest-Version: 1.0
Agent-Class: LoadedAgent

MANIFEST.MF

步骤:

1. 将LoadedAgent.class 和 Manifest.mf打进jar包

2. 执行TargetVM.class 获取进程号PID

3. 执行Test.class pid作为参数

  

注意:

1. 编译时需要用到jdk中lib目录下的tools.jar  javac -cp tools.jar Test.java

2. 执行命令(1244 是进程号) :java -classpath "D:/AOP/agentmain/tools.jar" Test 1244

java instrumentation &JVMTI的更多相关文章

  1. Java Instrumentation插桩技术学习

    Instrumentation基础 openrasp中用到了Instrumentation技术,它的最大作用,就是类的动态改变和操作. 使用Instrumentation实际上也可以可以开发一个代理来 ...

  2. Java - Instrumentation

    使用JRebel启动工程时加上VM参数时有一个参数是"-javaagent:D:\jrebel_5.6.0\jrebel.jar". javaagent是什么? java -hel ...

  3. 曹工说Spring Boot源码(25)-- Spring注解扫描的瑞士军刀,ASM + Java Instrumentation,顺便提提Jar包破解

    写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...

  4. java高级-动态注入替换类Instrumentation

    介绍 利用java.lang.instrument(容器类) 做动态 Instrumentation(执行容器) 是 Java SE 5 的新特性. 使用 Instrumentation,开发者可以构 ...

  5. 极客时间-左耳听风-程序员攻略-Java底层知识

    Java 字节码相关 字节码编程,也就是动态修改或是动态生成 Java 字节码.Java 的字节码相当于汇编,其中的一些细节. Java Zone: Introduction to Java Byte ...

  6. java agent技术原理及简单实现

    注:本文定义-在函数执行前后增加对应的逻辑的操作统称为MOCK 1.引子 在某天与QA同学进行沟通时,发现QA同学有针对某个方法调用时,有让该方法停止一段时间的需求,我对这部分的功能实现非常好奇,因此 ...

  7. Java 动态调试技术原理及实践

    本文转载自Java 动态调试技术原理及实践 导语 断点调试是我们最常使用的调试手段,它可以获取到方法执行过程中的变量信息,并可以观察到方法的执行路径.但断点调试会在断点位置停顿,使得整个应用停止响应. ...

  8. Java 中的纤程库 – Quasar

    来源:鸟窝, colobu.com/2016/07/14/Java-Fiber-Quasar/ 如有好文章投稿,请点击 → 这里了解详情 最近遇到的一个问题大概是微服务架构中经常会遇到的一个问题: 服 ...

  9. java基础-01基本概念

    java的特点 跨平台 所谓的平台,我们可以理解为操作系统. 大部分语言是不能跨平台的,比如c语言的程序在windows和linux上需要编写不同的代码. java程序是运行在JVM(Java Vir ...

随机推荐

  1. CMake error:System Error:No such file or directory CMake error:Could not open file for write in copy operation xxxx.ros_Config.cmake.tmp.

    微型电脑或嵌入式与电脑还是有点不同的,在微型电脑上ros indigo 版本下利用catkin编译如果你遇到如下错误: CMake error:System Error:No such file or ...

  2. poj 2226(最小覆盖)

    题目链接:http://poj.org/problem?id=2226 思路:将连续的横向水洼看成X集合中的一个点,连续的纵向水洼看成Y集合中的一个点,而将每个水点看成一条边,它连接了所在的X集合中的 ...

  3. 构造方法、this和super

    1.构造方法概述 创建对象的时候会调用构造方法.创建对象时需要给对象的属性初始化,这时需要有参的构造方法. 构造方法的格式: 修饰符 构造方法名(参数列表) { } 构造方法的体现: 构造方法没有返回 ...

  4. cocos2d-x:Layer::setPosition

    如果Node的实际类型是Layer或者其派生类, setPosition是不是有猫腻? std::string menuImage = "menu.png"; auto menuI ...

  5. jmeter对响应结果做正则、json、xpath结果测试

    上面的返回结果可用于关联取值测试 具体用法详见http://www.cnblogs.com/xinjing-jingxin/p/8554338.html http://goessner.net/art ...

  6. HDU4027(Can you answer these queries?)

    题目链接:传送门 题目大意:有一个长度为n的数组,有m次操作,每次操作输入 v x y,v==0时x~y区间内的数都开平方并且向下取整,v==1时求x~y区间内所有数的和. 题目思路:long lon ...

  7. Palindrome Function

    Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 256000/256000 K (Java/Others)Total Submissio ...

  8. 微信小程序开发遇见的问题之一

    在开发的时候,因为要定位到当前的城市,而小程序提供的API只是能够获取当前的经纬度,所以我们需要通过接入百度地图的API.调接口的时候发现报错,说域名不合法,此时千万不要着急,只要你登录你的微信开发公 ...

  9. ipv4 ipv6 在系统可扩展性方面的应用 支撑公司10-100年的AmazonOrderId

    w 如同 基因 生态系统 理念 思维 算法

  10. 2014-08-28——移动端web开发,基本Meta标签

    1.<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scal ...