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 ...
随机推荐
- SQL金典
ps:补充自己的基础知识,大神请无视.. ~~~~~~~~~~~~~~~~~~~~~ DataBase Management System,DBMS.... Catalog ...库 Table... ...
- python3----函数(join)
今天写python 100例时,有个题目是大致是这样的:已知输入形式是1+3+2+1,要求输出形式为1+1+2+3 一开始思路是将输入的字符串用split()函数划分成数组,在对数组进行排序,再用fo ...
- 有关于iOS字体的设置
1.网上搜索字体文件(后缀名为.ttf,或.odf) 2.把字体库导入到工程的resouce中 3.在程序viewdidload中加载一下一段代码 NSArray *familyNames = [UI ...
- 2、ACE-实用生活口语-介绍 Introductions
(1) (2) (3)认识你很荣幸,如何称呼您呢?It's a pleasure to meet you.I'm glad to meet you.May I have your name?How s ...
- 【BZOJ4898】[Apio2017]商旅 分数规划+SPFA
[BZOJ4898][Apio2017]商旅 Description 在广阔的澳大利亚内陆地区长途跋涉后,你孤身一人带着一个背包来到了科巴.你被这个城市发达而美丽的市场所深深吸引,决定定居于此,做一个 ...
- 【BZOJ2648】SJY摆棋子 KDtree
[BZOJ2648]SJY摆棋子 Description 这天,SJY显得无聊.在家自己玩.在一个棋盘上,有N个黑色棋子.他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找 ...
- Fennec VS. Snuke
Fennec VS. Snuke Time limit : 2sec / Memory limit : 256MB Score : 400 points Problem Statement Fenne ...
- easy 正则表达式验证 封装
基于EasyUI ValidateBox 的表单验证,可以直接写正则表达式. 在页面加载时执行下面代码 if ($.fn.form) { $.extend($.fn.validatebox.defau ...
- js实现还可输入多少个字
// 还可输入的字数个数 function checkLength(obj, len) { var maxChars = len; if (obj.value.length <= maxChar ...
- 《Tensorflow技术解析与实战》第四章
Tensorflow基础知识 Tensorflow设计理念 (1)将图的定义和图的运行完全分开,因此Tensorflow被认为是一个"符合主义"的库 (2)Tensorflow中涉 ...