jvm加载java的过程主要是:

编写java文件-》进行java文件的编译-》生成.class字节码文件-》jvm通过类加载器去加载生成的二进制文件

java编译器将源码文件编译称为二进制的.class文件

为什么要进行字节码增强操作?

不想修改源码,但是又想加入新功能,让程序按照我们的预期去运行,可以通过编译过程和加载过程中去做

相应的操作,

简单来讲就是:将生成的.class文件修改或者替换称为我们需要的目标.class文件。

需要依赖第三方的工具去实现字节码增强

这里使用javassist实现;

步骤:

/**
* 步骤1:编写你最初的业务类,实现业务功能
*/
public class BaseService {
public void basePrint(Map map){
System.out.println(map.toString());
}
}
/**
* 步骤2:编写你需要的对业务类进行增强的类或者内容
*/
public class ExBaseService {
public static void exPrint(Map map){
System.out.println("exbaseService增强的功能==需要增强的方法之前");
} public static void exPrintL(Map map){
System.out.println("exbaseService增强的功能==需要增强的方法之后");
}
}
/**
* 步骤3:编写增强的工具类,之后直接调用后再使用原来的业务类方法就实现增强了
* ClassPool其实是一张保存了CtClass信息的哈希表,key=类的全限定类名,value=类名对应的CtClass对象。
* 当需要对某个类修改的时候,通过方法getCtClass(className)从classpool获取到相应的CtClass
* CtClass:编译时的类信息,一个class文件在代码中的抽象表现形式,全限定类名可以获取CtClass对象,用于表示这个类文件
* CtMethod: 类中的方法 定义或修改
* CtField: 类中的属性 定义或修改
*
* javassist 增强代码片段是字符串编写,以$开头用于表示方法或构造函数参数或方法返回值
*/
public class ServiceUtils {
public static void done() throws NotFoundException, CannotCompileException {
ClassPool classPool = ClassPool.getDefault();//获取默认的类池
//通过全限定类名从类池获取对应需要增强的类
CtClass base = classPool.getOrNull("com.quan.security.intecepter.BaseService");
if (base == null){
System.out.println("can not found");
return;
}
//通过方法getDeclaredMethod和类中需要增强的方法名字得到CtMethod类型的方法抽象
CtMethod basemethod = base.getDeclaredMethod("basePrint");
//组合增强字符串,使用$1获取方法的参数。
StringBuffer sbf = new StringBuffer();
sbf.append("{");
sbf.append("com.quan.security.intecepter.ExBaseService.exPrint($1);");
sbf.append("}"); //进行增强,调用之前增强
basemethod.insertBefore(sbf.toString()); StringBuffer sbf2 = new StringBuffer();
sbf2.append("{");
sbf2.append("com.quan.security.intecepter.ExBaseService.exPrintL($1);");
sbf2.append("}"); //进行增强,调用需要增强方法之后增强
basemethod.insertAfter(sbf2.toString());
//替换增强后的字节码
base.toClass();
}
}
public class IntecepterTest {
/**
* 调用增强工具类,使最初的业务类进行增强,
* 随后调用业务类,查看是否增强
* @param args
*/
public static void main(String[] args) {
try {
ServiceUtils.done();
} catch (NotFoundException e) {
e.printStackTrace();
} catch (CannotCompileException e) {
e.printStackTrace();
}
BaseService baseService = new BaseService();
Map<String,String> map1 = new HashMap<>();
map1.put("name","quan");
baseService.basePrint(map1);
}
}

结果:

exbaseService增强的功能==需要增强的方法之前
{name=quan}
exbaseService增强的功能==需要增强的方法之后

字节码增强-learnning的更多相关文章

  1. 深入浅出Java探针技术1--基于java agent的字节码增强案例

    Java agent又叫做Java 探针,本文将从以下四个问题出发来深入浅出了解下Java agent 一.什么是java agent? Java agent是在JDK1.5引入的,是一种可以动态修改 ...

  2. JVM——字节码增强技术简介

    Java字节码增强指的是在Java字节码生成之后,对其进行修改,增强其功能,这种方式相当于对应用程序的二进制文件进行修改.Java字节码增强主要是为了减少冗余代码,提高性能等. 实现字节码增强的主要步 ...

  3. JVM插庄之一:JVM字节码增强技术介绍及入门示例

    字节码增强技术:AOP技术其实就是字节码增强技术,JVM提供的动态代理追根究底也是字节码增强技术. 目的:在Java字节码生成之后,对其进行修改,增强其功能,这种方式相当于对应用程序的二进制文件进行修 ...

  4. SpringAOP之CGLIB字节码增强

    SpringAOP的基础原理就是动态代理 有两种实现方式:1)jdk动态代理 2)cglib动态代理 jdk动态代理和cglib动态代理的区别在于: cglib没有接口(通过继承父类) 只有实现类.  ...

  5. JDK动态代理和CGLIB字节码增强

    一.JDK动态代理 Java 在 java.lang.reflect 包中有自己的代理支持,该类(Proxy.java)用于动态生成代理类,只需传入目标接口.目标接口的类加载器以及 Invocatio ...

  6. Java字节码增强探秘

    Java字节码增强探秘 https://mp.weixin.qq.com/s/CH9D-E7fxuu462Q2S3t0AA

  7. 从底层入手,解析字节码增强和Btrace应用

    这篇文章聊下字节码和相关的应用. 1.机器码和字节码 机器码(machine code),学名机器语言指令,有时也被称为原生码(Native Code),是电脑的CPU可直接解读的数据. 通常意义上来 ...

  8. 字节码增强技术-Byte Buddy

    本文转载自字节码增强技术-Byte Buddy 为什么需要在运行时生成代码? Java 是一个强类型语言系统,要求变量和对象都有一个确定的类型,不兼容类型赋值都会造成转换异常,通常情况下这种错误都会被 ...

  9. Java字节码增强技术

    简单介绍下几种java字节码增强技术. ASM ASM是一个Java字节码操控框架,它能被用来动态生成类或者增强既有类的功能.ASM可以直接产生class文件,也可以在类被加载入Java虚拟机之前动态 ...

随机推荐

  1. NSSCTF-no_wakeup

    打开网页是一个派萌的表情包(原神玩家手动狗头) 按照题目的提示点击,出现题目的源码, 观察题目源码,发现就是一个简单的反序列化,这边手打一下php (自己太菜了,枯了) <?phpclass H ...

  2. 简单excel饼状图怎么做,bi工具怎么做饼状图

    饼状图是为了在一个整体体现个体所占的比例,比如一块蛋糕每人各分多大份.了解了饼状图的含义,就来学习饼状图怎么做吧. 首先,我们准备excel表格饼状图的初始数据 然后选择excel表格上方的插入,选择 ...

  3. MySQL第三讲

    昨日内容回顾 公钥私钥 数据库存储引擎 MyISAM 是5.5版本之前默认的存储引擎 存取数据的速度较快.但是安全性偏差 三个文件 结构.索引.数据 InnoDB 5.5版本及之后默认的存储引擎 存取 ...

  4. redis数据类型的使用及介绍

    Redis数据类型 1.Sting类型 set命令 设置键值,存在则覆盖,不存在则新建 set key value EX 秒 设置有效时长为秒 nx 如果键不存在则新建,如果存在返回nil xx 只有 ...

  5. Go代码规范梳理

    Go代码规范(Code Review) 总结几个开发过程中经常会犯的代码规范错误 参考链接:https://learnku.com/go/wikis/48375 注释语句 // Request 表示运 ...

  6. 面向对象编程(C++篇2)——构造

    目录 1. 引述 2. 详述 2.1. 数据类型初始化 2.2. 类初始化 1. 引述 在C++中,学习类的第一课往往就是构造函数.根据构造函数的定义,构造函数式是用于初始化类对象的数据成员的.无论何 ...

  7. ajax发送json格式与文件数据、django自带的序列化器(了解)

    上期内容回顾 聚合查询和分组查询 # 聚合查询 max min sum avg count # 查询关键字:aggregate from django.db.models import Max, Mi ...

  8. Chapter09 项目

    Chapter09 项目 房屋出租系统(面向对象中级) 9.1 房屋出租系统-需求 9.1.1项目需求说明 实现基于文本界面的<房屋出租软件>. 能够实现对房屋信息的添加.修改和删除(用数 ...

  9. kubernetes StatefulSet控制器

    想学习更多相关知识请看博主的个人博客地址:https://blog.huli.com/ https://blog.huli.com/ 在Kubernetes系统中,Pod的管理对象RC.Deploym ...

  10. HTML 基础及超链接练习

    实验一:HTML 基础及超链接练习 实验目的: 熟悉 HTML 基础及超链接的使用 实验要求: 1.建立至少 3 个以上的网页: 2.实现任意两网页之间的跳转(建议做个导航菜单): 3.每个网页里面至 ...