用ASM直接读取字节码来加载Class的Annotation
来源:互联网 发布:选择旅行社的软件 编辑:程序博客网 时间:2024/06/06 09:10
转自http://blog.chinaunix.net/uid-254237-id-2458630.html
用ASM直接读取字节码来加载Class的Annotation2008-06-11 21:50:58
分类: Java
Asm是很好的ByteCode generator 和 ByteCode reader。Asm提供了ClassVisitor来访问Class中的每个元素。当用ClassReader来读取Class的字节码时,每read一个元素,ASM会调用指定的ClassVisitor来访问这个元素。这就是访问者模式。利用这个特点,当ClassVisitor访问Class的Annotation元素时,我们会把annotation的信息记录下来。这样就可以在将来使用这个Annotation。
举一个例子吧,我们用AnnotationFaker来标注一个Class,也就是Annotation的target是Type级别。当我们发现某个class是用AnnotationFaker标注的,我们就load这个class到jvm中,并初始化,否则免谈。
1.AnnotationFaker: annnotation用来标注需要初始化的class
2.ClassFaker: 被AnnotationFaker标注的class
3.ClassVisitorFaker:ClassVisitor的一个实现,用来得到class上的Annotation
4.ClassParser: main class, 分析classpath上的class,如果是用AnnotationFaker标注的class,我们就初始化它。
举一个例子吧,我们用AnnotationFaker来标注一个Class,也就是Annotation的target是Type级别。当我们发现某个class是用AnnotationFaker标注的,我们就load这个class到jvm中,并初始化,否则免谈。
1.AnnotationFaker: annnotation用来标注需要初始化的class
1package com.oocl.isdc.sha.frm.test.config;
2
3import java.lang.annotation.ElementType;
4import java.lang.annotation.Retention;
5import java.lang.annotation.RetentionPolicy;
6import java.lang.annotation.Target;
7
8@Retention(RetentionPolicy.RUNTIME)
9@Target({ElementType.TYPE})
10public @interface AnnotationFaker {
11}
12
2
3import java.lang.annotation.ElementType;
4import java.lang.annotation.Retention;
5import java.lang.annotation.RetentionPolicy;
6import java.lang.annotation.Target;
7
8@Retention(RetentionPolicy.RUNTIME)
9@Target({ElementType.TYPE})
10public @interface AnnotationFaker {
11}
12
2.ClassFaker: 被AnnotationFaker标注的class
1package com.oocl.isdc.sha.frm.test.config;
2
3@AnnotationFaker
4public class ClassFaker {
5 public void hello() {
6 System.out.println("hello world, load me success!");
7 }
8}
9
2
3@AnnotationFaker
4public class ClassFaker {
5 public void hello() {
6 System.out.println("hello world, load me success!");
7 }
8}
9
3.ClassVisitorFaker:ClassVisitor的一个实现,用来得到class上的Annotation
1package com.oocl.isdc.sha.frm.test.config;
2
3import java.util.ArrayList;
4import java.util.List;
5
6import org.objectweb.asm.AnnotationVisitor;
7import org.objectweb.asm.Attribute;
8import org.objectweb.asm.ClassVisitor;
9import org.objectweb.asm.FieldVisitor;
10import org.objectweb.asm.MethodVisitor;
11import org.objectweb.asm.tree.AnnotationNode;
12
13public class ClassVisitorFaker implements ClassVisitor{
14
15 public List<AnnotationNode> visibleAnnotations;
16
17 public List<AnnotationNode> invisibleAnnotations;
18
19 public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
20
21 }
22
23 public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
24 AnnotationNode an = new AnnotationNode(desc);
25 if (visible) {
26 if (visibleAnnotations == null) {
27 visibleAnnotations = new ArrayList<AnnotationNode> (1);
28 }
29 visibleAnnotations.add(an);
30 } else {
31 if (invisibleAnnotations == null) {
32 invisibleAnnotations = new ArrayList<AnnotationNode> (1);
33 }
34 invisibleAnnotations.add(an);
35 }
36 return an;
37 }
38
39 public void visitAttribute(Attribute attr) {
40 }
41
42 public void visitEnd() {
43 }
44
45 public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
46 return null;
47 }
48
49 public void visitInnerClass(String name, String outerName, String innerName, int access) {
50 }
51
52 public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
53 return null;
54 }
55
56 public void visitOuterClass(String owner, String name, String desc) {
57 }
58
59 public void visitSource(String source, String debug) {
60 }
61
62 public List<AnnotationNode> getVisibleAnnotations() {
63 return visibleAnnotations;
64 }
65
66 public List<AnnotationNode> getInvisibleAnnotations() {
67 return invisibleAnnotations;
68 }
69}
70
2
3import java.util.ArrayList;
4import java.util.List;
5
6import org.objectweb.asm.AnnotationVisitor;
7import org.objectweb.asm.Attribute;
8import org.objectweb.asm.ClassVisitor;
9import org.objectweb.asm.FieldVisitor;
10import org.objectweb.asm.MethodVisitor;
11import org.objectweb.asm.tree.AnnotationNode;
12
13public class ClassVisitorFaker implements ClassVisitor{
14
15 public List<AnnotationNode> visibleAnnotations;
16
17 public List<AnnotationNode> invisibleAnnotations;
18
19 public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
20
21 }
22
23 public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
24 AnnotationNode an = new AnnotationNode(desc);
25 if (visible) {
26 if (visibleAnnotations == null) {
27 visibleAnnotations = new ArrayList<AnnotationNode> (1);
28 }
29 visibleAnnotations.add(an);
30 } else {
31 if (invisibleAnnotations == null) {
32 invisibleAnnotations = new ArrayList<AnnotationNode> (1);
33 }
34 invisibleAnnotations.add(an);
35 }
36 return an;
37 }
38
39 public void visitAttribute(Attribute attr) {
40 }
41
42 public void visitEnd() {
43 }
44
45 public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
46 return null;
47 }
48
49 public void visitInnerClass(String name, String outerName, String innerName, int access) {
50 }
51
52 public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
53 return null;
54 }
55
56 public void visitOuterClass(String owner, String name, String desc) {
57 }
58
59 public void visitSource(String source, String debug) {
60 }
61
62 public List<AnnotationNode> getVisibleAnnotations() {
63 return visibleAnnotations;
64 }
65
66 public List<AnnotationNode> getInvisibleAnnotations() {
67 return invisibleAnnotations;
68 }
69}
70
4.ClassParser: main class, 分析classpath上的class,如果是用AnnotationFaker标注的class,我们就初始化它。
1package com.oocl.isdc.sha.frm.test.config;
2
3import java.io.File;
4import java.io.IOException;
5import java.net.URISyntaxException;
6import java.net.URL;
7import java.util.Enumeration;
8import java.util.HashSet;
9import java.util.Iterator;
10import java.util.List;
11import java.util.Set;
12import java.util.zip.ZipEntry;
13import java.util.zip.ZipException;
14import java.util.zip.ZipFile;
15
16import org.objectweb.asm.ClassReader;
17import org.objectweb.asm.Type;
18import org.objectweb.asm.tree.AnnotationNode;
19
20public class ClassParser {
21 @SuppressWarnings("unchecked")
22 public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, URISyntaxException {
23 Enumeration<URL> urls = getClassLoader().getResources(".");
24 Set<String> result = new HashSet<String>();
25 while(urls.hasMoreElements()) {
26 URL url = urls.nextElement();
27 File file = new File(url.toURI());
28 if (file.isDirectory()) {
29 handleDirectory(result, file, null);
30 } else {
31 handleArchive(result, file);
32 }
33 }
34
35 for(String clsRsName : result) {
36 ClassVisitorFaker cv = new ClassVisitorFaker();
37 ClassReader cr = new ClassReader(getClassLoader().getResourceAsStream(clsRsName));
38 cr.accept(cv, 0);
39 List<AnnotationNode> annotationsList = cv.getVisibleAnnotations();
40 if(null != annotationsList) {
41 for(Iterator<AnnotationNode> it = annotationsList.iterator(); it.hasNext();) {
42 AnnotationNode annotation = it.next();
43 Type t = Type.getType(annotation.desc);
44 if(AnnotationFaker.class.getName().equals(t.getClassName())) {
45 Class clazz = Class.forName(filenameToClassname(clsRsName));
46 ClassFaker faker = (ClassFaker) clazz.newInstance();
47 faker.hello();
48 }
49 }
50 }
51
52 }
53
54 }
55
56 private static void handleDirectory(final Set<String> result, final File file, final String path) {
57 for (final File child : file.listFiles()) {
58 final String newPath = path == null ? child.getName() : path + '/' + child.getName();
59 if (child.isDirectory()) {
60 handleDirectory(result, child, newPath);
61 } else {
62 handleItem(result, newPath);
63 }
64 }
65 }
66
67 private static void handleItem(final Set<String> result, final String name) {
68 if (name.endsWith(".class")) {
69 result.add(name);
70 }
71 }
72
73 private static void handleArchive(final Set<String> result, final File file) throws ZipException, IOException {
74 final ZipFile zip = new ZipFile(file);
75 final Enumeration<? extends ZipEntry> entries = zip.entries();
76 while (entries.hasMoreElements()) {
77 final ZipEntry entry = entries.nextElement();
78 final String name = entry.getName();
79 handleItem(result, name);
80 }
81 }
82
83 private static ClassLoader getClassLoader() {
84 ClassLoader clsLoader = Thread.currentThread().getContextClassLoader();
85 if(clsLoader == null) {
86 clsLoader = ClassLoader.getSystemClassLoader();
87 }
88 return clsLoader;
89 }
90
91
92 public static String filenameToClassname(final String filename) {
93 return filename.substring(0, filename.lastIndexOf(".class")).replace('/', '.').replace('\\', '.');
94 }
95
96
97}
2
3import java.io.File;
4import java.io.IOException;
5import java.net.URISyntaxException;
6import java.net.URL;
7import java.util.Enumeration;
8import java.util.HashSet;
9import java.util.Iterator;
10import java.util.List;
11import java.util.Set;
12import java.util.zip.ZipEntry;
13import java.util.zip.ZipException;
14import java.util.zip.ZipFile;
15
16import org.objectweb.asm.ClassReader;
17import org.objectweb.asm.Type;
18import org.objectweb.asm.tree.AnnotationNode;
19
20public class ClassParser {
21 @SuppressWarnings("unchecked")
22 public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, URISyntaxException {
23 Enumeration<URL> urls = getClassLoader().getResources(".");
24 Set<String> result = new HashSet<String>();
25 while(urls.hasMoreElements()) {
26 URL url = urls.nextElement();
27 File file = new File(url.toURI());
28 if (file.isDirectory()) {
29 handleDirectory(result, file, null);
30 } else {
31 handleArchive(result, file);
32 }
33 }
34
35 for(String clsRsName : result) {
36 ClassVisitorFaker cv = new ClassVisitorFaker();
37 ClassReader cr = new ClassReader(getClassLoader().getResourceAsStream(clsRsName));
38 cr.accept(cv, 0);
39 List<AnnotationNode> annotationsList = cv.getVisibleAnnotations();
40 if(null != annotationsList) {
41 for(Iterator<AnnotationNode> it = annotationsList.iterator(); it.hasNext();) {
42 AnnotationNode annotation = it.next();
43 Type t = Type.getType(annotation.desc);
44 if(AnnotationFaker.class.getName().equals(t.getClassName())) {
45 Class clazz = Class.forName(filenameToClassname(clsRsName));
46 ClassFaker faker = (ClassFaker) clazz.newInstance();
47 faker.hello();
48 }
49 }
50 }
51
52 }
53
54 }
55
56 private static void handleDirectory(final Set<String> result, final File file, final String path) {
57 for (final File child : file.listFiles()) {
58 final String newPath = path == null ? child.getName() : path + '/' + child.getName();
59 if (child.isDirectory()) {
60 handleDirectory(result, child, newPath);
61 } else {
62 handleItem(result, newPath);
63 }
64 }
65 }
66
67 private static void handleItem(final Set<String> result, final String name) {
68 if (name.endsWith(".class")) {
69 result.add(name);
70 }
71 }
72
73 private static void handleArchive(final Set<String> result, final File file) throws ZipException, IOException {
74 final ZipFile zip = new ZipFile(file);
75 final Enumeration<? extends ZipEntry> entries = zip.entries();
76 while (entries.hasMoreElements()) {
77 final ZipEntry entry = entries.nextElement();
78 final String name = entry.getName();
79 handleItem(result, name);
80 }
81 }
82
83 private static ClassLoader getClassLoader() {
84 ClassLoader clsLoader = Thread.currentThread().getContextClassLoader();
85 if(clsLoader == null) {
86 clsLoader = ClassLoader.getSystemClassLoader();
87 }
88 return clsLoader;
89 }
90
91
92 public static String filenameToClassname(final String filename) {
93 return filename.substring(0, filename.lastIndexOf(".class")).replace('/', '.').replace('\\', '.');
94 }
95
96
97}
代码中,需要引入org.objectweb.asm-3.3.1.v201105211655.jar包。因为博客不能穿附件,会上传到资源处。
阅读全文
0 0
- 用ASM直接读取字节码来加载Class的Annotation
- 用ASM直接读取字节码来加载Class的Annotation
- Java 字节码操控框架ASM(二):Parsing class
- jvm第9节-asm生成class字节码
- java字节码框架ASM的学习
- asm-giude阅读笔记003(ASM核心API接口和对应组件---读取字节码)
- Java字节码框架ASM-读写字节码的用法
- Java字节码框架ASM-读写字节码的用法
- Java字节码框架ASM-读写字节码的用法
- ASM读写字节码
- Java 类加载器及加载Class字节码
- Class的字节码文件
- 使用字节码asm将pojo转换成Map,直接构造mongodb bsonobject
- 通过反射和class文件asm字节码分析方法是get或者set方法
- Java 字节码操控框架ASM(一):创建class文件
- Dalvik 字节码的读取
- 字节码操作(ObjectWeb ASM)
- asm动态生成字节码
- [LeetCode]1. Two Sum
- h5、js最详细的正则检验手机号码
- 一元隐函数及其求导
- 解决全站乱码的过滤器实现-包装类设计模式的应用
- socket-详细分析No buffer space available
- 用ASM直接读取字节码来加载Class的Annotation
- PXE+Kickstart无人值守安装CentOS 7出现DHCP故障解决报告
- linux 常用命令
- 冒泡排序 大的在上
- 查找算法之二分查找
- java并发中的Semaphore
- 174. Dungeon Game
- css media
- CentOS httpd服务启动失败:Cannot load /etc/httpd/modules/mod_ssl.so