Javasssist初探(需要对Java的ClassLoader机制有一些了解)

本文介绍如何使用Javassist库动态生成Java类。通过一个实例展示了自定义类加载器、接口及主测试类的实现过程。该技术可用于需要动态修改类的场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Javassist可以用来动态生成java类,就好像js可以生成可执行的js代码一样。javassist是JBoss的一个子项目,用处的话可能是在对EJB提供支持的时候,将声称各种接口的实现类和代理类。

下面给出一个例子,在这个例子中一共有三个类:DirectLoader自定义类加载器;IAccess是接口类(我们动态生成的类要实现这个接口);MainTest完成主要逻辑的类,其中javassist的使用也在这里面体现。下面给出三个类的源代码。需要使用javassist的jar包程序才能运行



//--------------DirectLoader------------------------------------
importjava.security.SecureClassLoader;

publicclassDirectLoaderextendsSecureClassLoader...{
protectedDirectLoader()...{

super(MainTest.class.getClassLoader());
}


protectedClassload(Stringname,byte[]data)...{
returnsuper.defineClass(name,data,0,data.length);
}

}



//--------------IAccess------------------------------------
importjava.util.List;

publicinterfaceIAccess...{
publicvoidCalculate(ListInVars)throwsException;
}



//--------------MainTest------------------------------------

importjava.util.List;

importjavassist.ClassPool;
importjavassist.CtClass;
importjavassist.CtConstructor;
importjavassist.CtMethod;

/**//*
*本类用来演示如何使用javassist动态生成
*/


publicclassMainTest...{
privatestaticfinalCtClass[]NO_ARGS=...{};

//privatestaticfinalCtClass[]INT_ARGS={CtClass.intType};

privatestaticbooleanisFirst=true;

//用这个标示标记是否需要重新生成新的类。
//一般情况下,我们没必要动态生成类,如果有这个必要
//就说明类需要动态改动并使用,所以,这个变量是很有用的
privatestaticbooleanneedReload=true;

privatestaticDirectLoaders_classLoader=newDirectLoader();

publicMainTest()...{
}


publicstaticvoidmain(String[]args)throwsException...{
execTest();
execTest();
}


/***//**
*执行代码
*
*
@throwsException
*/

publicstaticvoidexecTest()throwsException...{
Classclas
=null;
try...{
if(needReload)...{
clas
=createExecClass();
}
else...{
clas
=s_classLoader.loadClass("ExecVar");
}

}
catch(ClassNotFoundExceptione)...{
System.out.println(
"没有这个类,动态生成");
clas
=createExecClass();
}

//使用动态生成的类,最好是使用接口。否则就只能通过反射调用其方法了
IAccessaccess=null;
try...{
access
=(IAccess)clas.newInstance();
}
catch(IllegalAccessExceptionex)...{
ex.printStackTrace(System.err);
System.exit(
1);
}
catch(InstantiationExceptionex)...{
ex.printStackTrace(System.err);
System.exit(
1);
}

List
<String>list=newjava.util.ArrayList<String>();
list.add(
"ThisisaString");
//通过借口的引用调用我们动态生成的类的
access.Calculate(list);
}


privatestaticClasscreateExecClass()throwsException...{
//ClassPool是javasssit中的类,作用嘛,自描述的
ClassPoolpool=ClassPool.getDefault();
CtClassclas
=null;
if(!isFirst)...{
//如果不是第一次,就必须要将原来的类在pool中作废,
//否则无法在同一个pool中生成新的类
//具体做法是否正确,有待进一步考证
pool=ClassPool.getDefault();
clas
=pool.get("ExecVar");
if(clas.isFrozen())...{
System.out
.println(
"ClassExecVarisfrozen,Pleaselookingforsomethingthatcanmakeitunfrozen!");
//clas.defrost();
//从pool中拆离这个类
clas.detach();
}

}

isFirst
=false;

//动态生成一个类
clas=pool.makeClass("ExecVar");
clas.addInterface(pool.get(
"IAccess"));
//增加默认的构造方法
CtConstructorcons=newCtConstructor(NO_ARGS,clas);
cons.setBody(
";");
clas.addConstructor(cons);

//增加一个方法,参数为java.util.List,返回值是空,名字叫做Calculate,所属类是clas
CtMethodmeth=newCtMethod(CtClass.voidType,"Calculate",
newCtClass[]...{pool.get("java.util.List")},clas);
//用这个随机数检测是否是新生成的类
doublerandom=Math.random();
meth.setBody(
"System.out.println("这是一个reload测试:"+$1.get(0)+",随机数:"
+random+"");");
//将方法加入其中
clas.addMethod(meth);
//创建一个新的ClassLoader,以加载新的生成的类,旧的s_classLoader连同旧的
//ExecVar类一起被废弃
s_classLoader=newDirectLoader();
returns_classLoader.load("ExecVar",clas.toBytecode());
}

}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值