本人初学,我也搞得不是很明白,目前只做出这个demo, asm那些操作具体是什么意思,请查看asm的api 。
性能方面,没测试
废话不多说了,直接上代码
首先把自定义的类加器搞上来
package net;
public class MyClassLoader extends ClassLoader
{
@SuppressWarnings("unchecked")
public Class defineClassByName(String name,byte[] b,int off,int len){
Class clazz = super.defineClass(name,b, off, len);
return clazz;
}
}
下面上动态生成class的代码,visit方法的第一个参数为class的版本号,jdk1.6的用49,目前没有找到每个jdk所对应的class文件版本号。
package net;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.GeneratorAdapter;
import org.objectweb.asm.commons.Method;
public class AsmDemo
{
@SuppressWarnings("unchecked")
public static void main(String[] args)
{
/*生成类文件的结构,代码现在是这样
* public class HelloWorld{
*
* }
*/
ClassWriter cw=new ClassWriter(ClassWriter.COMPUTE_MAXS);
cw.visit(49, Opcodes.ACC_PUBLIC, "HelloWorld", null, "java/lang/Object", null);
Method m=Method.getMethod("void <init> ()");
GeneratorAdapter ga=new GeneratorAdapter(Opcodes.ACC_PUBLIC,m,null,null,cw);
ga.loadThis();
ga.invokeConstructor(Type.getType(Object.class), m);
ga.returnValue();
ga.endMethod();
/*
* 在HelloWorld中添加main方法,在main方法中添加代码,代码现在是这样子
* public class HelloWorld{
* public static void mian(String[] args){
* System.out.println("Hello World!");
* }
* }
*/
m = Method.getMethod("void main (String[])");
ga = new GeneratorAdapter(Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, m, null, null, cw);
ga.getStatic(Type.getType(System.class), "out", Type.getType(PrintStream.class));
ga.push("Hello World!");
ga.invokeVirtual(Type.getType(PrintStream.class), Method.getMethod("void println (String)"));
ga.returnValue();
ga.endMethod();
cw.visitEnd();
/*
* 这个方法用于后面的类动态加载测试,HelloWorld中的结构现在已经变成
* public class HelloWorld{
* public static void mian(String[] args){
* System.out.println("Hello World!");
* }
* public void doSomething(){
* System.out.println("动态生成,动态加载调用方法");
* }
* }
*/
m=Method.getMethod("void doSomething()");
ga=new GeneratorAdapter(Opcodes.ACC_PUBLIC,m,null,null,cw);
ga.getStatic(Type.getType(System.class), "out", Type.getType(PrintStream.class));
ga.push("动态生成,动态加载调用方法");
ga.invokeVirtual(Type.getType(PrintStream.class), Method.getMethod("void println(String)"));
ga.returnValue();
ga.endMethod();
MyClassLoader mcl=new MyClassLoader();
//利用自定义的类加载器把生成类文件加载到jvm 。
byte[] bytes=cw.toByteArray();
//返回的对象时被加载类的class
Class hw=mcl.defineClassByName("HelloWorld", bytes, 0, bytes.length);
try
{
//利用反射创建对象
Object o=hw.newInstance();
java.lang.reflect.Method method= o.getClass().getMethod("doSomething");
method.invoke(o);
/*把文件生成的class文件写入磁盘 File.separator为文件分隔符(知道的勿喷)
* ,它会根据操作系统不同,而自动转换,比直接写成\\这种通用性强。
* 这个路径原来一般写成d:\\HelloWorld.class
*/
File file=new File("d:"+File.separator+"HelloWorld.class");
FileOutputStream fos=new FileOutputStream(file);
fos.write(cw.toByteArray());
fos.flush();
fos.close();
}
catch (FileNotFoundException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (InstantiationException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IllegalAccessException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (SecurityException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (NoSuchMethodException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IllegalArgumentException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (InvocationTargetException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
运行这个控制台输出为
动态生成,动态加载调用方法
然后我们发现d多了个class文件,打开命令提示符切换到d盘,输入java HelloWorld
控制台输出
Hello World!
源码和所需Jar包在附件中
分享到:
相关推荐
ASM是一个开源的Java字节码操控和分析框架,它能够用来动态生成类或者增强已有类的功能。ASM可以被用来创建Java代理、实现元编程、甚至深入到Java虚拟机(JVM)层面进行性能优化。在Java开发中,ASM库允许我们直接...
ASM允许开发者在运行时动态生成和修改类。通过ASM,我们可以: - 创建全新的类、接口或继承已有类的子类。 - 修改已有的类,添加、删除或修改方法、字段。 - 在方法体中插入代码,实现AOP(面向切面编程)的动态代理...
这证明了ASM生成的字节码是有效的,并且可以被Java虚拟机执行。 ASM的用途广泛,不仅限于简单的类生成。它可以用于创建动态代理、字节码插桩、代码分析等复杂任务。通过深入理解ASM,开发者可以对Java字节码进行细...
Java动态生成代码并编译载入是Java编程中的一项高级技术,它允许程序在运行时创建新的类或接口,然后即时编译并加载到当前的Java虚拟机(JVM)中。这种技术主要依赖于Java的反射API和Java的编译器API(javac)或者更...
在给定的代码示例中,我们看到了如何使用ASM生成接口`sample.HelloWorld`的过程: 1. 首先,创建一个`ClassWriter`实例,传入`ClassWriter.COMPUTE_FRAMES`作为参数。这将使ASM自动处理堆栈映射帧的生成。 ```java ...
例如,当我们需要根据特定条件自动生成处理逻辑时,可以使用`JavaCompiler`类或者第三方库如Javassist、ByteBuddy等,将字符串形式的Java源代码编译为Class对象,然后实例化执行。 2. **动态加载**:在传统编程中,...
ASM4是中国Java开发者常用的一款字节码操作框架ASM的第四个主要版本,它主要用于动态生成和分析Java字节码。ASM是一个低级别的库,可以直接操作和生成类的字节码,这在创建编译器、代码分析工具以及运行时代码修改等...
ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。Java class 被存储在严格格式定义的 .class 文件里,这些类文件拥有足够的元数据来解析类中的所有元素:类名称、方法、属性...
总之,ASM的`ClassWriter`类提供了生成和修改Java字节码的强大能力,是深入理解字节码和进行动态字节码操作的基础。通过熟练掌握`ClassWriter`的使用,开发者可以实现很多高级功能,如运行时代码增强、性能监控、...
ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。Java class 被存储在严格格式定义的 .class 文件里,这些类文件拥有足够的元数据来解析类中的所有元素:类名称、方法、属性...
ASM、Javassist等库可以帮助我们动态地生成和修改字节码。 3. **代理模式**:使用Java的代理机制,可以在运行时创建新类的代理,从而实现热加载。例如,CGLIB和ASM库可以用来创建字节码代理,使得调用更新的类代码...
ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。Java class 被存储在严格格式定义的 .class 文件里,这些类文件拥有足够的元数据来解析类中的所有元素:类名称、方法、属性...
ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。Java class 被存储在严格格式定义的 .class 文件里,这些类文件拥有足够的元数据来解析类中的所有元素:类名称、方法、属性...
通过直接生成二进制`.class`文件,ASM能够在类被加载到Java虚拟机之前动态地改变类的行为。 - **应用场景**: - **程序分析**:用于查找应用程序中的潜在错误、检测未使用的代码以及实现代码逆向工程。 - **程序...
ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。Java class 被存储在严格格式定义的 .class文件里,这些类文件拥有足够的元数据来解析类中的所有元素:类名称、方法、属性...
ASM 可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为。Java class 被存储在严格格式定义的 .class 文件里,这些类文件拥有足够的元数据来解析类中的所有元素:类名称、方法、属性...
### JAVA类加载机制与动态代理 #### 一、类加载机制 ##### 1.1 类加载的时机 类加载机制负责将描述类的数据从`.class`文件加载到内存,并进行必要的校验、转换解析和初始化,使之成为可以被Java虚拟机直接使用的...
4. **构建和加载类**: 最后,使用ASM的ClassWriter生成新的字节码,然后通过DexClassLoader或其他类加载器动态加载到Android系统中。 MonitorDemo-master项目很可能包含了一个示例的Android无痕埋点框架实现,包括...
这个例子展示了ASM的基本用法,通过`ClassWriter`动态生成类、接口、字段和方法的字节码,这对于创建自定义的类加载器、运行时代码生成、AOP(面向切面编程)等场景非常有用。同时,由于ASM可以生成和修改字节码,它...