java instrumentation &JVMTI
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的更多相关文章
- Java Instrumentation插桩技术学习
Instrumentation基础 openrasp中用到了Instrumentation技术,它的最大作用,就是类的动态改变和操作. 使用Instrumentation实际上也可以可以开发一个代理来 ...
- Java - Instrumentation
使用JRebel启动工程时加上VM参数时有一个参数是"-javaagent:D:\jrebel_5.6.0\jrebel.jar". javaagent是什么? java -hel ...
- 曹工说Spring Boot源码(25)-- Spring注解扫描的瑞士军刀,ASM + Java Instrumentation,顺便提提Jar包破解
写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...
- java高级-动态注入替换类Instrumentation
介绍 利用java.lang.instrument(容器类) 做动态 Instrumentation(执行容器) 是 Java SE 5 的新特性. 使用 Instrumentation,开发者可以构 ...
- 极客时间-左耳听风-程序员攻略-Java底层知识
Java 字节码相关 字节码编程,也就是动态修改或是动态生成 Java 字节码.Java 的字节码相当于汇编,其中的一些细节. Java Zone: Introduction to Java Byte ...
- java agent技术原理及简单实现
注:本文定义-在函数执行前后增加对应的逻辑的操作统称为MOCK 1.引子 在某天与QA同学进行沟通时,发现QA同学有针对某个方法调用时,有让该方法停止一段时间的需求,我对这部分的功能实现非常好奇,因此 ...
- Java 动态调试技术原理及实践
本文转载自Java 动态调试技术原理及实践 导语 断点调试是我们最常使用的调试手段,它可以获取到方法执行过程中的变量信息,并可以观察到方法的执行路径.但断点调试会在断点位置停顿,使得整个应用停止响应. ...
- Java 中的纤程库 – Quasar
来源:鸟窝, colobu.com/2016/07/14/Java-Fiber-Quasar/ 如有好文章投稿,请点击 → 这里了解详情 最近遇到的一个问题大概是微服务架构中经常会遇到的一个问题: 服 ...
- java基础-01基本概念
java的特点 跨平台 所谓的平台,我们可以理解为操作系统. 大部分语言是不能跨平台的,比如c语言的程序在windows和linux上需要编写不同的代码. java程序是运行在JVM(Java Vir ...
随机推荐
- VC++ 汇编相关的东西
Tips: VC++在新建一个.asm文件后必须重新导入project中才能进行编译. 下面是一个汇编与C++相互调用的例子: Main.cpp #include <stdio.h> #i ...
- chm文件无法阅读
当我们费劲千辛万苦从网上下载好chm文件资料后,打开后发现竟然是这个样子的: 其中主要原因是CHM文件被阻止显示了,CHM文件在NTFS格式的硬盘里的时候就会被阻止显示.我们返回我的电脑,点中我们存放 ...
- filter和find区别,元素遍历
转 filter和find区别 find()会在当前指定元素中查找符合条件的子元素,是对它的子集操作,而filter()则是在当前指定的元素集合中查找符合条件的元素,是对自身集合元素进行筛选. HTM ...
- 1503 猪和回文(DP)
1503 猪和回文 题目来源: CodeForces 基准时间限制:2 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 一只猪走进了一个森林.很凑巧的是,这个森林的形状是长方形的,有 ...
- 安装IntelliJ IDEA 破解安装
IDEA 功能介绍 1-深度智力 IntelliJ IDEA为您的源代码编制索引后,通过在每个环境中提供相关建议,提供快速,智能的体验:即时和智能的代码完成,即时代码分析和可靠的重构工具. 2-开箱即 ...
- ID生成策略
在电商项目中,图片名.商品ID都要唯一且方便存储,于是记录下这两个ID生成策略的方法,以便日后项目再有需要.具体代码如下 import java.util.Random; /** * 图片名生成 */ ...
- 64位matlab mex64位编译器解决方案
安装libsvm的时候用到了mex -setup,有的会报 Could not find the 64-bit compiler. This may indicate that the "X ...
- PHP heredoc 用法2
参考网上的一个heredoc php模板实现的简单代码:index.php文件: <?php function template($template,$EXT ='htm') { $path = ...
- MySQL中事务的分类
从事务理论的角度来看,可以把事务分为以下几种类型 扁平事务(Flat Transactions) 带有保存点的扁平事务(Flat Transactions with Savepoints) 链事务(C ...
- Python3.6全栈开发实例[012]
12.输出商品列表,用户输入序号,显示用户选中的商品(升级题) 商品列表: goods = [{"name": "电脑", "price": ...