Java中ASM框架详解
什么是asm呢?asm是assembly的缩写,是汇编的称号,对于java而言,asm就是字节码级别的编程。
而这里说到的asm是指objectweb asm,一种.class的代码生成器的开源项目.
ASM是一套java字节码生成架构,它可以动态生成二进制格式的stub类或其它代理类,
或者在类被java虚拟机装入内存之前,动态修改类。
现在挺多流行的框架都使用到了asm.所以从aop追溯来到了这。
1.什么是ObjectWeb ASM
ObjectWeb ASM是轻量级的Java字节码处理框架。它可以动态生成二进制格式的stub类或其他代理类,或者在类被JAVA虚拟机装入内存之前,动态修改类。
ASM 提供了与 BCEL和SERP相似的功能,只有22K的大小,比起350K的BCEL和150K的SERP来说,是相当小巧的,并且它有更高的执行效率,
是BCEL 的7倍,SERP的11倍以上。
在我看来,ObjectWeb ASM具有如下几个非常诱人的特点
* 小巧、高效
* 源代码实现非常简洁而又优雅,简直就是Gof的《设计模式》非常棒的注解
* 字节码级的控制,能够更高效地实现字节码的控制
ObjectWeb ASM有2组接口:
* 基于事件驱动的接口,类似于xml的SAX接口,visitor模式,在访问到类定义某个部分的时候进行回调,实现上比tree接口高效,占用内存更小
* 基于tree的接口,类似于xml的DOM接口,将类定义解析成tree
这里我们将使用ObjectWeb ASM的事件驱动接口
2. 目标
我们将对已有的字节码进行增强,收集进入方法和退出方法的信息,这里主要解决Method Monitor的字节码增强部分,
不对收集后的数据处理做更深入地研究,出于演示的目的,我们定义了如下的收集方法的访问信息处理,
在实际应用中,我们可能会使用更好的格式收集更多的数据、使用异步处理提高性能、使用批量处理提高处理能力、使用友好的UI显示信息等等,
此处不对这部分进行探讨
1. package blackstar.methodmonitor.instrutment.monitor;
2. public class MonitorUtil
3. {
4. public final static String CLASS_NAME = MonitorUtil.class.getName()
5. .replaceAll("\\.", "/");
6. public final static String ENTRY_METHOD = "entryMethod";
7. public final static String EXIT_METHOD = "exitMethod";
8. public final static String METHOD = "(Ljava/lang/String;Ljava/lang/String;)V";
9.
10. public static void entryMethod(String className, String methodName)
11. {
12. System.out.println("entry : " + className + "." + methodName);
13. }
14.
15. public static void exitMethod(String className, String methodName)
16. {
17. System.out.println("exit : " + className + "." + methodName);
18. }
19. }
3. 从字节码开始
实际上,对于被监控制的代码,我们所需要实现的功能如下,红色部分的代码是我们需要在动态期插到字节码中间的
public xxx method(…)
{
try
{
methodEntry(…)
methodCode
}
finally
{
methodExit(…)
}
}
这个问题看起来简单,实际则没有那么容易,因为在JVM的字节码设计中,字节码并不直接支持finally语句,而是使用try…catch来模拟的,我们先来看一个例子
Java代码
1. package blackstar.methodmonitor.instrutment.test;
2.
3. public class Test
4. {
5. public void sayHello() throws Exception
6. {
7. try
8. {
9. System.out.println("hi");
10. } catch (Exception e)
11. {
12. System.out.println("exception");
13. return;
14. } finally
15. {
16. System.out.println("finally");
17. }
18. }
19. }
我们看看字节码是如何处理finally语句的
首先看看异常表,异常是在JVM级别上直接支持的,下面异常表的意思是,在执行0-8语句的时候,如果有异常java.lang.Exception抛出,则进入第11语句,
在执行0-20语句的时候,有任何异常抛出,都进入29语句。实际上JVM是这样实现finally语句的:
* 在任何return语句之前,都会增加finally语句中的字节码
* 定义一个捕获所有异常的语句,增加finally语句中的字节码,如果finally中没有return语句,则会将异常再次抛出去(处理方法以抛出异常的方式结束)
Exceptions:
[0-8): 11 - java.lang.Exception
[0-20): 29
我们再看看字节码具体是如何做的
0 getstatic java.lang.System.out
3 ldc "hi" (java.lang.String)
5 invokevirtual println
8 goto 40
// System.out.println("hi");,执行完之后执行返回(goto 40)
11 astore_1
12 getstatic java.lang.System.out
15 ldc "exception" (java.lang.String)
17 invokevirtual println
// System.out.println("exception");
20 getstatic java.lang.System.out
23 ldc "finally" (java.lang.String)
25 invokevirtual println
// return语句之前插入finally部分字节码
// System.out.println("finally");
28 return
29 astore_2
30 getstatic java.lang.System.out
33 ldc "finally" (java.lang.String)
35 invokevirtual println
38 aload_2
39 athrow
//当在执行0-29语句中,如果有异常抛出,则执行这段finally语句
//此处的astore_2(将栈顶值——即exception的地址——设给第2个local变量)和aload_2(将第2个local变量的值入栈)这两个字节码实际是不必要的,
//但需要注意的是,如果这2段代码去掉的话,要考虑增大操作栈(max stack)以容纳这个exception地址
//System.out.println("finally");
40 getstatic java.lang.System.out
43 ldc "finally" (java.lang.String)
45 invokevirtual println
// return语句之前插入finally部分字节码
// System.out.println("finally");
48 return
实际上,我们需要做的就是
* 在方法进入时插入方法进入代码(需要注意,对于构造函数不允许做这种处理,构造函数第一步必须调用父类的构造函数。
* 在每个return操作(包括return、ireturn、freturn等)之前,插入方法退出代码
* 定义一个捕获所有异常的处理,在处理中,插入方法退出代码(即方法以抛异常的方式终止执行)
4. 实现
我们看看使用ObjectWeb ASM如何实现我们上面描述的功能
1)ObjectWeb ASM的字节码修改
1. ClassReader cr = new ClassReader(byteArray); //使用字节码构监一个reader
2. ClassWriter cw = new ClassWriter(cr, 0);//writer将基于已有的字节码进行修改
3. MonitorClassVisitor ca = new MonitorClassVisitor(cw);//修改处理回调类
4. cr.accept(ca, 0);
Java中ASM框架详解的更多相关文章
- Java中日志组件详解
avalon-logkit Java中日志组件详解 lanhy 发布于 2020-9-1 11:35 224浏览 0收藏 作为开发人员,我相信您对日志记录工具并不陌生. Java还具有功能强大且功能强 ...
- java中的注解详解和自定义注解
一.java中的注解详解 1.什么是注解 用一个词就可以描述注解,那就是元数据,即一种描述数据的数据.所以,可以说注解就是源代码的元数据.比如,下面这段代码: @Override public Str ...
- Java中dimension类详解
Java中dimension类详解 https://blog.csdn.net/hrw1234567890/article/details/81217788
- [转载]java中import作用详解
[转载]java中import作用详解 来源: https://blog.csdn.net/qq_25665807/article/details/74747868 这篇博客讲的真的很清楚,这个作者很 ...
- Java中反射机制详解
序言 在学习java基础时,由于学的不扎实,讲的实用性不强,就觉得没用,很多重要的知识就那样一笔带过了,像这个马上要讲的反射机制一样,当时学的时候就忽略了,到后来学习的知识中,很多东西动不动就用反射, ...
- Java中的多线程详解
如果对什么是线程.什么是进程仍存有疑惑,请先Google之,因为这两个概念不在本文的范围之内. 用多线程只有一个目的,那就是更好的利用cpu的资源,因为所有的多线程代码都可以用单线程来实现.说这个话其 ...
- JAVA中Object类方法详解
一.引言 Object是java所有类的基类,是整个类继承结构的顶端,也是最抽象的一个类.大家天天都在使用toString().equals().hashCode().waite().notify() ...
- Java中Unsafe类详解
http://www.cnblogs.com/mickole/articles/3757278.html Java不能直接访问操作系统底层,而是通过本地方法来访问.Unsafe类提供了硬件级别的原子操 ...
- 一看你就懂,超详细java中的ClassLoader详解
本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 ClassLoader翻译过来就是类加载器,普通的Java开发者其实用到的不多,但对于某些框架开发者来说却非常常见.理解ClassL ...
随机推荐
- python object与dict互相转换
代码如下 # 将class转dict,以_开头的属性不要 def props(obj): pr = {} for name in dir(obj): value = getattr(obj, name ...
- scrapy之Pipeline
官方文档:https://docs.scrapy.org/en/latest/topics/item-pipeline.html 激活pipeline,需要在settings里配置,然而这里配置的pi ...
- 【NOIP2016练习】T1 string (计数)
题意: 思路: ; ..]of int64; n,k,i:longint; ans,x,y:int64; s,t:ansistring; function c(x,y:longint):int64; ...
- UML学习倒腾记
先看到http://www.jianshu.com/p/1256e2643923这篇博客,号称21分钟入门uml,也许是我太笨了吧,一下午也没有完全搞定: 使用过atom编辑器,没有完全运行出来结果. ...
- 44深入理解C指针之---指针安全
一.指针安全:指针的声明和初始化问题 1.指针不恰当的声明: 1).声明的意思和真是的意图不一致,可以通过格式搞定: 2).使用宏定义时,展开的含义有变,通过格式搞定: 3).使用类型定义,使用更加方 ...
- js判断鼠标滑轮滚动方向并根据滚动的方向触发不同的事件
<script> var scrollFunc = function (e) { var direct = 0; e = e || window.event; if (e.wheelDel ...
- 洛谷——P1220 关路灯
P1220 关路灯 题目描述 某一村庄在一条路线上安装了n盏路灯,每盏灯的功率有大有小(即同一段时间内消耗的电量有多有少).老张就住在这条路中间某一路灯旁,他有一项工作就是每天早上天亮时一盏一盏地关掉 ...
- git 撤回上一次commit中某一个不想添加的文件
1. 假设我们修改了文件a,同时修改了IDE的配置文件b 2.此时我们只想添加文件a到commit中,却不小心将b也添加进去了 3.那么怎么撤回呢? 4.第一种方法 :重新提交commit 5. 第二 ...
- openfire Android学习(六)----总结
Xmpp的一些方法整理到一个工具类中了 XmppConnection.java [java] view plaincopy [java] view plaincopy import java.io.B ...
- win10拷贝文件卡顿的问题-竟然是winrar搞的
win10拷贝文件卡顿的问题-竟然是winrar搞的 学习了: http://www.w10zj.com/Win10xy/Win10xf_3378.html 没想到你竟然是这样的WinRAR 去除了s ...